@matheusbsbs / matheus-bagliano / commits / 8415d5c7ef
Fork 0

Teach the "@{-1} syntax to "git branch"

This teaches the new "@{-1} syntax to refer to the previous branch to "git branch". After looking at somebody's faulty patch series on a topic branch too long, if you decide it is not worth merging, you can just say: $ git checkout master $ git branch -D @{-1} to get rid of it without having to type the name of the topic you now hate so much for wasting a lot of your time. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Feb 13, 2009 at 23:08 UTC 8415d5c7ef63237f6efab0c9aef0b0fdbcbfda25
3 files changed +59 -17
branch.c
+14 -5
@@ -103,14 +103,22 @@ void create_branch(const char *head,
103 struct ref_lock *lock;
104 struct commit *commit;
105 unsigned char sha1[20];
106 - char *real_ref, ref[PATH_MAX], msg[PATH_MAX + 20];
106 + char *real_ref, msg[PATH_MAX + 20];
107 + struct strbuf ref = STRBUF_INIT;
108 int forcing = 0;
109 + int len;
110
109 - snprintf(ref, sizeof ref, "refs/heads/%s", name);
110 - if (check_ref_format(ref))
111 + len = strlen(name);
112 + if (interpret_nth_last_branch(name, &ref) != len) {
113 + strbuf_reset(&ref);
114 + strbuf_add(&ref, name, len);
115 + }
116 + strbuf_splice(&ref, 0, 0, "refs/heads/", 11);
117 +
118 + if (check_ref_format(ref.buf))
119 die("'%s' is not a valid branch name.", name);
120
113 - if (resolve_ref(ref, sha1, 1, NULL)) {
121 + if (resolve_ref(ref.buf, sha1, 1, NULL)) {
122 if (!force)
123 die("A branch named '%s' already exists.", name);
124 else if (!is_bare_repository() && !strcmp(head, name))
@@ -142,7 +150,7 @@ void create_branch(const char *head,
150 die("Not a valid branch point: '%s'.", start_name);
151 hashcpy(sha1, commit->object.sha1);
152
145 - lock = lock_any_ref_for_update(ref, NULL, 0);
153 + lock = lock_any_ref_for_update(ref.buf, NULL, 0);
154 if (!lock)
155 die("Failed to lock ref for update: %s.", strerror(errno));
156
@@ -162,6 +170,7 @@ void create_branch(const char *head,
170 if (write_ref_sha1(lock, sha1, msg) < 0)
171 die("Failed to write ref: %s.", strerror(errno));
172
173 + strbuf_release(&ref);
174 free(real_ref);
175 }
176
builtin-branch.c
+19 -12
@@ -99,6 +99,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
99 const char *fmt, *remote;
100 int i;
101 int ret = 0;
102 + struct strbuf bname = STRBUF_INIT;
103
104 switch (kinds) {
105 case REF_REMOTE_BRANCH:
@@ -119,20 +120,25 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
120 if (!head_rev)
121 die("Couldn't look up commit object for HEAD");
122 }
122 - for (i = 0; i < argc; i++) {
123 - if (kinds == REF_LOCAL_BRANCH && !strcmp(head, argv[i])) {
123 + for (i = 0; i < argc; i++, strbuf_release(&bname)) {
124 + int len = strlen(argv[i]);
125 +
126 + if (interpret_nth_last_branch(argv[i], &bname) != len)
127 + strbuf_add(&bname, argv[i], len);
128 +
129 + if (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) {
130 error("Cannot delete the branch '%s' "
125 - "which you are currently on.", argv[i]);
131 + "which you are currently on.", bname.buf);
132 ret = 1;
133 continue;
134 }
135
136 free(name);
137
132 - name = xstrdup(mkpath(fmt, argv[i]));
138 + name = xstrdup(mkpath(fmt, bname.buf));
139 if (!resolve_ref(name, sha1, 1, NULL)) {
140 error("%sbranch '%s' not found.",
135 - remote, argv[i]);
141 + remote, bname.buf);
142 ret = 1;
143 continue;
144 }
@@ -152,22 +158,23 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
158 if (!force &&
159 !in_merge_bases(rev, &head_rev, 1)) {
160 error("The branch '%s' is not an ancestor of "
155 - "your current HEAD.\n"
156 - "If you are sure you want to delete it, "
157 - "run 'git branch -D %s'.", argv[i], argv[i]);
161 + "your current HEAD.\n"
162 + "If you are sure you want to delete it, "
163 + "run 'git branch -D %s'.", bname.buf, bname.buf);
164 ret = 1;
165 continue;
166 }
167
168 if (delete_ref(name, sha1, 0)) {
169 error("Error deleting %sbranch '%s'", remote,
164 - argv[i]);
170 + bname.buf);
171 ret = 1;
172 } else {
173 struct strbuf buf = STRBUF_INIT;
168 - printf("Deleted %sbranch %s (%s).\n", remote, argv[i],
169 - find_unique_abbrev(sha1, DEFAULT_ABBREV));
170 - strbuf_addf(&buf, "branch.%s", argv[i]);
174 + printf("Deleted %sbranch %s (%s).\n", remote,
175 + bname.buf,
176 + find_unique_abbrev(sha1, DEFAULT_ABBREV));
177 + strbuf_addf(&buf, "branch.%s", bname.buf);
178 if (git_config_rename_section(buf.buf, NULL) < 0)
179 warning("Update of config-file failed");
180 strbuf_release(&buf);
t/t0100-previous.sh new
+26
@@ -0,0 +1,26 @@
1 +#!/bin/sh
2 +
3 +test_description='previous branch syntax @{-n}'
4 +
5 +. ./test-lib.sh
6 +
7 +test_expect_success 'branch -d @{-1}' '
8 + test_commit A &&
9 + git checkout -b junk &&
10 + git checkout - &&
11 + test "$(git symbolic-ref HEAD)" = refs/heads/master &&
12 + git branch -d @{-1} &&
13 + test_must_fail git rev-parse --verify refs/heads/junk
14 +'
15 +
16 +test_expect_success 'branch -d @{-12} when there is not enough switches yet' '
17 + git reflog expire --expire=now &&
18 + git checkout -b junk2 &&
19 + git checkout - &&
20 + test "$(git symbolic-ref HEAD)" = refs/heads/master &&
21 + test_must_fail git branch -d @{-12} &&
22 + git rev-parse --verify refs/heads/master
23 +'
24 +
25 +test_done
26 +