Re: [PATCH] git-checkout.txt: improve detached HEAD documentation
- From
Jay Soffian <jaysoffian@gmail.com>
- Date
- Feb 17, 2011, 19:48 UTC
- Message-ID
- <AANLkTi=tp2KasvPxSsHgQp3DqEHfMX6w+re7s+UYPVJ+@mail.gmail.com>
- In-Reply-To
- <1297971966-58500-1-git-send-email-jaysoffian@gmail.com>
On Thu, Feb 17, 2011 at 2:46 PM, Jay Soffian <jaysoffian@gmail.com> wrote:
> The detached HEAD state is a source of much confusion for users > new to git. Here we try to document it better. > > Reworked from http://article.gmane.org/gmane.comp.version-control.git/138440
The patch may be difficult to read, so here's the man output after applying the patch:
DETACHED HEAD
HEAD normally refers to a named branch (e.g. "master"). Meanwhile, each
branch refers to a specific commit-id. Let's look at a repo with three
commits and with "master" checked out: HEAD (refers to master)
v
a---b---c master (refers to c) When a commit is created in this state, the branch is updated to the
new commit-id. Let's add a commit: HEAD (refers to master)
v
a---b---c---d master (refers to d) It is sometimes useful to be able to checkout a commit that is not at
the tip of any named branch, or even to create a new commit that is not
referenced by a named branch. Let's look at what happens when we
checkout commit b:$ git checkout master^^
HEAD (refers to b)
v
a---b---c---d master (refers to d) Notice that HEAD now refers directly to commit b. In git terminology,
this is known as having a detached HEAD. It means simply that HEAD
refers to a specific commit-id, as opposed to referring to a named
branch. Let's add a commit while HEAD is detached: HEAD (refers to e)
v
e
/
a---b---c---d master (refers to d) We have created a new commit, but it is referenced only by HEAD. We can
of course add yet another commit in this state: HEAD (refers to f)
v
e---f
/
a---b---c---d master (refers to d) In fact, we can perform all the normal git operations. But, let's look
at what happens when we then checkout master:$ git checkout master
e---f HEAD (refers to master)
/ v
a---b---c---d master (refers to d) It is important to realize that at this point nothing refers to commits
e and f. Eventually these commits will be deleted by the routine git
garbage collection process, unless we create a reference before that
happens. If we have not yet moved away from commit f, any of these will
create a reference to it: $ git checkout -b foo # (1)
$ git branch foo # (2)
$ git tag foo # (3) (1) creates a new branch "foo", which refers to f, and then updates
HEAD to refer to "foo". In other words, we'll no longer be in detached
HEAD state after (1). (2) similarly creates a new branch "foo", which refers to f, but leaves
HEAD detached.(3) creates a new tag "foo", which refers to f, leaving HEAD detached.
If we have moved away from commit f, then we must first recover its id
(typically by using git reflog), and then we can create a reference to
it. For example, to see the last two commits to which HEAD referred, we
can use:$ git log -g -2 HEAD