Skip to content

Commit 99f45c2

Browse files
committed
Merge branch 'js/detach-doc'
* js/detach-doc: git-checkout.txt: improve detached HEAD documentation
2 parents 5e3d39b + be8ef33 commit 99f45c2

File tree

1 file changed

+121
-23
lines changed

1 file changed

+121
-23
lines changed

Documentation/git-checkout.txt

Lines changed: 121 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -215,40 +215,138 @@ leave out at most one of `A` and `B`, in which case it defaults to `HEAD`.
215215

216216
DETACHED HEAD
217217
-------------
218+
HEAD normally refers to a named branch (e.g. 'master'). Meanwhile, each
219+
branch refers to a specific commit. Let's look at a repo with three
220+
commits, one of them tagged, and with branch 'master' checked out:
218221

219-
It is sometimes useful to be able to 'checkout' a commit that is
220-
not at the tip of one of your branches. The most obvious
221-
example is to check out the commit at a tagged official release
222-
point, like this:
222+
------------
223+
HEAD (refers to branch 'master')
224+
|
225+
v
226+
a---b---c branch 'master' (refers to commit 'c')
227+
^
228+
|
229+
tag 'v2.0' (refers to commit 'b')
230+
------------
231+
232+
When a commit is created in this state, the branch is updated to refer to
233+
the new commit. Specifically, 'git commit' creates a new commit 'd', whose
234+
parent is commit 'c', and then updates branch 'master' to refer to new
235+
commit 'd'. HEAD still refers to branch 'master' and so indirectly now refers
236+
to commit 'd':
223237

224238
------------
225-
$ git checkout v2.6.18
239+
$ edit; git add; git commit
240+
241+
HEAD (refers to branch 'master')
242+
|
243+
v
244+
a---b---c---d branch 'master' (refers to commit 'd')
245+
^
246+
|
247+
tag 'v2.0' (refers to commit 'b')
226248
------------
227249

228-
Earlier versions of git did not allow this and asked you to
229-
create a temporary branch using the `-b` option, but starting from
230-
version 1.5.0, the above command 'detaches' your HEAD from the
231-
current branch and directly points at the commit named by the tag
232-
(`v2.6.18` in the example above).
250+
It is sometimes useful to be able to checkout a commit that is not at
251+
the tip of any named branch, or even to create a new commit that is not
252+
referenced by a named branch. Let's look at what happens when we
253+
checkout commit 'b' (here we show two ways this may be done):
233254

234-
You can use all git commands while in this state. You can use
235-
`git reset --hard $othercommit` to further move around, for
236-
example. You can make changes and create a new commit on top of
237-
a detached HEAD. You can even create a merge by using `git
238-
merge $othercommit`.
255+
------------
256+
$ git checkout v2.0 # or
257+
$ git checkout master^^
258+
259+
HEAD (refers to commit 'b')
260+
|
261+
v
262+
a---b---c---d branch 'master' (refers to commit 'd')
263+
^
264+
|
265+
tag 'v2.0' (refers to commit 'b')
266+
------------
239267

240-
The state you are in while your HEAD is detached is not recorded
241-
by any branch (which is natural --- you are not on any branch).
242-
What this means is that you can discard your temporary commits
243-
and merges by switching back to an existing branch (e.g. `git
244-
checkout master`), and a later `git prune` or `git gc` would
245-
garbage-collect them. If you did this by mistake, you can ask
246-
the reflog for HEAD where you were, e.g.
268+
Notice that regardless of which checkout command we use, HEAD now refers
269+
directly to commit 'b'. This is known as being in detached HEAD state.
270+
It means simply that HEAD refers to a specific commit, as opposed to
271+
referring to a named branch. Let's see what happens when we create a commit:
247272

248273
------------
249-
$ git log -g -2 HEAD
274+
$ edit; git add; git commit
275+
276+
HEAD (refers to commit 'e')
277+
|
278+
v
279+
e
280+
/
281+
a---b---c---d branch 'master' (refers to commit 'd')
282+
^
283+
|
284+
tag 'v2.0' (refers to commit 'b')
250285
------------
251286

287+
There is now a new commit 'e', but it is referenced only by HEAD. We can
288+
of course add yet another commit in this state:
289+
290+
------------
291+
$ edit; git add; git commit
292+
293+
HEAD (refers to commit 'f')
294+
|
295+
v
296+
e---f
297+
/
298+
a---b---c---d branch 'master' (refers to commit 'd')
299+
^
300+
|
301+
tag 'v2.0' (refers to commit 'b')
302+
------------
303+
304+
In fact, we can perform all the normal git operations. But, let's look
305+
at what happens when we then checkout master:
306+
307+
------------
308+
$ git checkout master
309+
310+
HEAD (refers to branch 'master')
311+
e---f |
312+
/ v
313+
a---b---c---d branch 'master' (refers to commit 'd')
314+
^
315+
|
316+
tag 'v2.0' (refers to commit 'b')
317+
------------
318+
319+
It is important to realize that at this point nothing refers to commit
320+
'f'. Eventually commit 'f' (and by extension commit 'e') will be deleted
321+
by the routine git garbage collection process, unless we create a reference
322+
before that happens. If we have not yet moved away from commit 'f',
323+
any of these will create a reference to it:
324+
325+
------------
326+
$ git checkout -b foo <1>
327+
$ git branch foo <2>
328+
$ git tag foo <3>
329+
------------
330+
331+
<1> creates a new branch 'foo', which refers to commit 'f', and then
332+
updates HEAD to refer to branch 'foo'. In other words, we'll no longer
333+
be in detached HEAD state after this command.
334+
335+
<2> similarly creates a new branch 'foo', which refers to commit 'f',
336+
but leaves HEAD detached.
337+
338+
<3> creates a new tag 'foo', which refers to commit 'f',
339+
leaving HEAD detached.
340+
341+
If we have moved away from commit 'f', then we must first recover its object
342+
name (typically by using git reflog), and then we can create a reference to
343+
it. For example, to see the last two commits to which HEAD referred, we
344+
can use either of these commands:
345+
346+
------------
347+
$ git reflog -2 HEAD # or
348+
$ git log -g -2 HEAD
349+
------------
252350

253351
EXAMPLES
254352
--------

0 commit comments

Comments
 (0)