On Tue, Mar 27 2018, Aaron Greenberg wrote: > This patch gives git-branch the ability to delete the previous > checked-out branch using the "-" shortcut. This shortcut already exists > for git-checkout, git-merge, and git-revert. A common workflow is > > 1. Do some work on a local topic-branch and push it to a remote. > 2. 'remote/topic-branch' gets merged in to 'remote/master'. > 3. Switch back to local master and fetch 'remote/master'. > 4. Delete previously checked-out local topic-branch. > > $ git checkout -b topic-a > $ # Do some work... > $ git commit -am "Implement feature A" > $ git push origin topic-a > > $ git checkout master > $ git branch -d topic-a > $ # With this patch, a user could simply type > $ git branch -d - > > "-" is a useful shortcut for cleaning up a just-merged branch > (or a just switched-from branch.) > > Signed-off-by: Aaron Greenberg <p@xxxxxxxxxxxxxxxxxxx> So just a tip on this E-Mail chain/patch submission. When you submit a v2 make the subject "[PATCH v2] ...", see Documentation/SubmittingPatches, also instead of sending two mails with the same subject better to put any comments not in the commit message... > --- ...right here, below the triple dash, and CC the people commenting on the initial thread. With that, some comments on the change below: > builtin/branch.c | 3 +++ > t/t3200-branch.sh | 8 ++++++++ > 2 files changed, 11 insertions(+) > > diff --git a/builtin/branch.c b/builtin/branch.c > index 6d0cea9..9e37078 100644 > --- a/builtin/branch.c > +++ b/builtin/branch.c > @@ -221,6 +221,9 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, > char *target = NULL; > int flags = 0; > > + if (!strcmp(argv[i], "-")) > + argv[i] = "@{-1}"; > + If we just do this, then when I do the following: 1. be on the 'foo' branch 2. checkout 'bar', commit 3. checkout 'foo' 4. git branch -d - I get this message: error: The branch 'bar' is not fully merged. If you are sure you want to delete it, run 'git branch -D bar' While that works, I think it's better UI for us to suggest what's actually the important alternation to the user's command, i.e. replace -d with -D, otherwise they'll think "oh '-' doesn't work, let's try to name the branch", only to get the same error. I.e. this on top: diff --git a/builtin/branch.c b/builtin/branch.c index cdf2de4f1d..081a4384ce 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -157,17 +157,18 @@ static int branch_merged(int kind, const char *name, static int check_branch_commit(const char *branchname, const char *refname, const struct object_id *oid, struct commit *head_rev, - int kinds, int force) + int kinds, int force, int resolved_dash) { struct commit *rev = lookup_commit_reference(oid); if (!rev) { - error(_("Couldn't look up commit object for '%s'"), refname); + error(_("Couldn't look up commit object for '%s'"), resolved_dash ? "-" : refname); return -1; } if (!force && !branch_merged(kinds, branchname, rev, head_rev)) { error(_("The branch '%s' is not fully merged.\n" "If you are sure you want to delete it, " - "run 'git branch -D %s'."), branchname, branchname); + "run 'git branch -D %s'."), branchname, + resolved_dash ? "-" : branchname); return -1; } return 0; @@ -220,9 +221,12 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, for (i = 0; i < argc; i++, strbuf_reset(&bname)) { char *target = NULL; int flags = 0; + int resolved_dash = 0; - if (!strcmp(argv[i], "-")) + if (!strcmp(argv[i], "-")) { argv[i] = "@{-1}"; + resolved_dash = 1; + } strbuf_branchname(&bname, argv[i], allowed_interpret); free(name); @@ -255,7 +259,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, if (!(flags & (REF_ISSYMREF|REF_ISBROKEN)) && check_branch_commit(bname.buf, name, &oid, head_rev, kinds, - force)) { + force, resolved_dash)) { ret = 1; goto next; } There are other error messages there, but as far as I can tell it's best if those just talk about the "bar" branch, but have a look. A test for that with i18ngrep left as an exercise... > strbuf_branchname(&bname, argv[i], allowed_interpret); > free(name); > name = mkpathdup(fmt, bname.buf); > diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh > index 6c0b7ea..78c25aa 100755 > --- a/t/t3200-branch.sh > +++ b/t/t3200-branch.sh > @@ -776,6 +776,14 @@ test_expect_success 'deleting currently checked out branch fails' ' > test_must_fail git branch -d my7 > ' > > +test_expect_success 'test deleting last branch' ' > + git checkout -b my7.1 && > + git checkout - && > + test_path_is_file .git/refs/heads/my7.1 && > + git branch -d - && > + test_path_is_missing .git/refs/heads/my7.1 > +' > + > test_expect_success 'test --track without .fetch entries' ' > git branch --track my8 && > test "$(git config branch.my8.remote)" && I don't know how much this applies to the existing commands you mentioned (looks like not), but for "branch" specifically this looks very incomplete, in particular: * There's other modes where it takes commit-ish, e.g. "git branch foo bar" to create a new branch foo starting at bar, but with your patch "git branch foo -" won't work, even though there's no reason not to think it does. * There's no docs here to explain this difference, or TODO tests for maybe making that work later. Your patch would be a lot easier to review if you went through t/t3200-branch.sh, found the commit-ish occurances you don't support, and added failing tests for those, and explain in the commit message something to the effect of "I'm only making *this* work, here's the cases that *don't* work".