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 <[email protected]>
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".