git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Undocumented change in `git branch -M` behavior

From
NANish Aravamudan <nish.aravamudan@canonical.com>
Date
Aug 23, 2017, 20:13 UTC
Message-ID
<20170823201334.bz42s6t5ti4jdaqm@pitfall>
Hello,

Hopefully, I've got this right -- I noticed a change in behavior in git with Ubuntu 17.10, which recently got 2.14.1. Specifically, that when in an orphaned branch, -M ends up moving HEAD to the new branch name, clobbering the working tree. As far as I know, from the manpages, orphaned branches are still supported and should work?

I think an example will demonstrate more than words (the following are done in LXD containers, hence the root user):

# git --version
git version 2.14.1
# mkdir test && cd test && git init .
Initialized empty Git repository in /root/test/.git/
# git checkout -b a
Switched to a new branch 'a'
# touch testfile && git add testfile && git commit -m 'initial commit'
[a (root-commit) 6061193] initial commit
 Committer: root <root@precious-magpie.lxd>
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 testfile
# git checkout --orphan master
Switched to a new branch 'master'
# git status
On branch master
No commits yet
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   testfile

# git reset --hard && git status On branch master

No commits yet
nothing to commit (create/copy files and use "git add" to track)
# git branch -M a b
# git status
On branch b
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
        deleted:    testfile

This is very unexpected. I force-renamed a branch I wasn't currently checked out to and now I'm checked out to it *and* I have staged file removals (I think what is effectively happening is my current working directory (empty) is being staged into the new branch, but I'm not 100%).

For comparision, on 17.04:
# git --version
git version 2.11.0
# mkdir test && cd test && git init .
Initialized empty Git repository in /root/test/.git/
# git checkout -b a
Switched to a new branch 'a'
# touch testfile && git add testfile && git commit -m 'initial commit'
[a (root-commit) f8d0d53] initial commit
 Committer: root <root@honest-sturgeon.lxd>
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 testfile
# git checkout --orphan master
Switched to a new branch 'master'
# git status
On branch master
No commits yet
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   testfile

# git reset --hard && git status On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track) # git branch -M a b # git status On branch master

Initial commit
nothing to commit (create/copy files and use "git add" to track)
This is what I expect to see, the branch rename has no effect on HEAD.

I haven't yet bisected this (but I can if necessary). My initial suspicion is https://github.com/git/git/commit/70999e9ceca47e03b8900bfb310b2f804125811e#diff-d18f86ea14e2f1e5bff391b2e54438cb where a comparison between the oldname of the branch and HEAD was performed before attempting to move HEAD (so that HEAD followed to the new branch name, I believe). That change was dropped, though and perhaps the new check in replace_each_worktree_head_symref of

        strcmp(oldref, worktrees[i]->head_ref)

does not work for orphaned branches? I am unfamiliar with all the details of the git internals, so please correct me if I'm wrong!

Thanks, Nish

-- 
Nishanth Aravamudan
Ubuntu Server
Canonical Ltd
Next: Kevin Daudt
Message 1 of 6 in “Undocumented change in `git branch -M` behavior”
  1. Nish AravamudanAug 23, 2017
  2. Kevin DaudtAug 24, 2017
  3. Duy NguyenAug 24, 2017
  4. Fix branch renaming not updating HEADs correctlyNguyễn Thái Ngọc Duy, Aug 24, 2017
  5. Nish AravamudanAug 24, 2017
  6. Junio C HamanoAug 27, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.