Git checkout refs / heads / master disables HEAD
I have a local branch "master" tracking the remote branch "origin / master".
When I check the master like this:
git checkout refs/heads/master
I end up with a separate head:
Note: checking "refs / heads / master".
You are in a detached HEAD state. You can look around, do experimental changes and commits, and you can discard any commits you make in this state without affecting any branches by doing another checkout.
Obviously, I could just check the "master", but that could be an ambiguous link. I just want to know what the "git way" is to disambiguate the branch name without separating the HEAD.
source to share
The documentation for git checkout
does not say how it behaves when master
ambiguous. After looking at the source code (I moved quickly so I might be wrong), it looks like it git checkout
assumes the name provided (for example master
) is the name of the branch until it finds what's in refs/heads/*
for the given name.
So the correct way to check out a branch when the revision is ambiguous is to leave the value refs/heads/
, for example git checkout master
.
From branching and revision
Note that there is a subtle but important difference between specifying a branch and specifying a revision (or other object). For commands and options that accept a revision (or shared object), the hint is the master
same as the job refs/heads/master
, unless master
it is ambiguous. It also matches the hint master^0
or SHA1 it points to master
, etc.
For commands and options that take a branch (for example, git branch
or --branches
for commands of type git log
), the specification is master
not the same as the assignment refs/heads/master
. In these cases, the full line is refs/heads/master
interpreted as the name of the branch, causing Git to create / checkout / update the ref with the name refs/heads/refs/heads/master
instead refs/heads/master
.
The command is git checkout
versatile, which is handy, but can be confusing in cases like master
vs. refs/heads/master
... When you point master
and a ref with a name refs/heads/master
exists, git checkout
assumes that you mean the branch master
and not the revision it points to master
. When you point refs/heads/master
and the ref with a name refs/heads/refs/heads/master
does not exist, it git checkout
assumes that you meant the revision you are pointing master
to and not the named branch refs/heads/master
(so you get detached HEAD
).
Checking non-interface when ambiguous
If you want to check out some other ref whose short name is also master
(like a tag with a name master
), you will need to specify the full name of the link (for example git checkout refs/tags/master
) or incantation of revision in a way that cannot be interpreted as a valid branch name (for example git checkout master^0
) ... The latter results in git checkout
following the ambiguity rules described in git help revisions
:
When ambiguous, a
<refname>
is disambiguated by accepting the first match in the following rules:
- If
$GIT_DIR/<refname>
there is, this is what you have in mind (usually only useful forHEAD
,FETCH_HEAD
,ORIG_HEAD
,MERGE_HEAD
andCHERRY_PICK_HEAD
);- otherwise
refs/<refname>
, if it exists;- otherwise
refs/tags/<refname>
, if it exists;- otherwise
refs/heads/<refname>
, if it exists;- otherwise
refs/remotes/<refname>
, if it exists;- otherwise
refs/remotes/<refname>/HEAD
, if it exists.
Of course, the result will be a separate one HEAD
, but this always happens when you checkout a non-branch.
source to share