fix: don't create a local branch named HEAD - #3014
Open
VXNCXNX wants to merge 1 commit into
Open
Conversation
origin/HEAD is a symbolic ref pointing at the remote's default branch, but checkout_remote_branch derived the local name from the ref text, so it created and checked out a branch literally called HEAD. Resolve the symref first and check out its target. Its local counterpart usually already exists from the clone, so switch to it, but only when it points at the same commit, since a diverged local branch is not what was asked for. Fixes gitui-org#2681.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2681.
The problem
origin/HEADis a symbolic ref pointing at the remote's default branch, butcheckout_remote_branchderived the local name from the ref text. So checking it out produced a local branch literally namedHEAD:That's from a test against a real fixture — a bare remote, a clone with
refs/remotes/origin/HEAD, thencheckout_remote_branchon it.The fix
Resolve the symref first, then derive the name from what it actually points at:
origin/HEADbecomesorigin/master, so the local name ismasterand noHEADbranch is created. That matches whatgit checkout origin/HEADgives you.The part that needed a second pass
Resolving alone isn't enough: the branch
origin/HEADpoints at is the one checked out at clone time, so the localmasteralready exists andrepo.branch()fails with "a reference with that name already exists".My first version handled that by falling back to the existing local branch whenever one was found. A review caught that this is a silent-wrong-commit bug, and I confirmed it:
The user asks for
origin/fooand silently lands on their stale localfoo. The pre-existing error is confusing, but it's honest, and it does reach the user (InternalEvent::ShowErrorMsg).So the fallback is now conditional on the existing local branch pointing at the same commit:
which is exactly the
origin/HEADcase and nothing else. Diverged local branches keep the old error.Tests
Two, both against real fixtures using the existing
repo_init_bare/repo_clone/push_branchhelpers:test_checkout_remote_head— checking outorigin/HEADlands onmasterand creates no branch namedHEAD. Verified load-bearing: with the production change reverted it fails with the assertion quoted above.test_checkout_remote_branch_diverged_local— pins that a diverged local branch is not silently substituted.(
asyncgitneeds--features vendor-opensslin my environment for lack of system OpenSSL.)CHANGELOG entry added under
## Unreleased.