branch: fix "copy" to never touch HEAD

When creating a new branch B by copying the branch A that happens to be the current branch, it also updates HEAD to point at the new branch. It probably was made this way because "git branch -c A B" piggybacked its implementation on "git branch -m A B", This does not match the usual expectation. If I were sitting on a blue chair, and somebody comes and repaints it to red, I would accept ending up sitting on a chair that is now red (I am also OK to stand, instead, as there no longer is my favourite blue chair). But if somebody creates a new red chair, modelling it after the blue chair I am sitting on, I do not expect to be booted off of the blue chair and ending up on sitting on the new red one. Let's fix this before it hits 'next'. Those who want to create a new branch and switch to it can do "git checkout B" after doing a "git branch -c B", and if that operation is so useful and deserves a short-hand way to do so, perhaps extend "git checkout -b B" to copy configurations while creating the new branch B. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Sep 22, 2017 at 12:24 UTC e5435ff1fc64d93cce73ec4ee2571219384a92a9
2 files changed +8 -11
builtin/branch.c
+3 -6
@@ -506,12 +506,9 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
506 oldref.buf + 11);
507 }
508
509 - if (replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf)) {
510 - if (copy)
511 - die(_("Branch copied to %s, but HEAD is not updated!"), newname);
512 - else
513 - die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
514 - }
509 + if (!copy &&
510 + replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf))
511 + die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
512
513 strbuf_release(&logmsg);
514
t/t3200-branch.sh
+5 -5
@@ -422,7 +422,7 @@ test_expect_success 'git branch --copy is a synonym for -c' '
422 test_cmp expect actual
423 '
424
425 -test_expect_success 'git branch -c ee ef should copy and checkout branch ef' '
425 +test_expect_success 'git branch -c ee ef should copy ee to create branch ef' '
426 git checkout -b ee &&
427 git reflog exists refs/heads/ee &&
428 git config branch.ee.dummy Hello &&
@@ -431,7 +431,7 @@ test_expect_success 'git branch -c ee ef should copy and checkout branch ef' '
431 git reflog exists refs/heads/ef &&
432 test $(git config branch.ee.dummy) = Hello &&
433 test $(git config branch.ef.dummy) = Hello &&
434 - test $(git rev-parse --abbrev-ref HEAD) = ef
434 + test $(git rev-parse --abbrev-ref HEAD) = ee
435 '
436
437 test_expect_success 'git branch -c f/f g/g should work' '
@@ -494,12 +494,12 @@ test_expect_success 'git branch -C c1 c2 should succeed when c1 is checked out'
494 git checkout -b c1 &&
495 git branch c2 &&
496 git branch -C c1 c2 &&
497 - test $(git rev-parse --abbrev-ref HEAD) = c2
497 + test $(git rev-parse --abbrev-ref HEAD) = c1
498 '
499
500 -test_expect_success 'git branch -C c1 c2 should add entries to .git/logs/HEAD' '
500 +test_expect_success 'git branch -C c1 c2 should never touch HEAD' '
501 msg="Branch: copied refs/heads/c1 to refs/heads/c2" &&
502 - grep "$msg$" .git/logs/HEAD
502 + ! grep "$msg$" .git/logs/HEAD
503 '
504
505 test_expect_success 'git branch -C master should work when master is checked out' '