Merge branch 'js/detach-doc'
authorJunio C Hamano <gitster@pobox.com>
Mon, 28 Feb 2011 05:58:30 +0000 (21:58 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 28 Feb 2011 05:58:30 +0000 (21:58 -0800)
* js/detach-doc:
git-checkout.txt: improve detached HEAD documentation

1  2 
Documentation/git-checkout.txt
index 87863fcadc74646689be18d401339372769f16fd,ca8b7d1ba3637ea5d46a7331ad0b09fe2b67b27c..396f4cc15bff745e72e137239dbd49e6584e23d2
@@@ -9,7 -9,6 +9,7 @@@ SYNOPSI
  --------
  [verse]
  'git checkout' [-q] [-f] [-m] [<branch>]
 +'git checkout' [-q] [-f] [-m] [--detach] [<commit>]
  'git checkout' [-q] [-f] [-m] [[-b|-B|--orphan] <new_branch>] [<start_point>]
  'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...
  'git checkout' --patch [<tree-ish>] [--] [<paths>...]
@@@ -23,10 -22,9 +23,10 @@@ branch
  
  'git checkout' [<branch>]::
  'git checkout' -b|-B <new_branch> [<start point>]::
 +'git checkout' [--detach] [<commit>]::
  
        This form switches branches by updating the index, working
 -      tree, and HEAD to reflect the specified branch.
 +      tree, and HEAD to reflect the specified branch or commit.
  +
  If `-b` is given, a new branch is created as if linkgit:git-branch[1]
  were called and then checked out; in this case you can
@@@ -117,13 -115,6 +117,13 @@@ explicitly give a name with '-b' in suc
        Create the new branch's reflog; see linkgit:git-branch[1] for
        details.
  
 +--detach::
 +      Rather than checking out a branch to work on it, check out a
 +      commit for inspection and discardable experiments.
 +      This is the default behavior of "git checkout <commit>" when
 +      <commit> is not a branch name.  See the "DETACHED HEAD" section
 +      below for details.
 +
  --orphan::
        Create a new 'orphan' branch, named <new_branch>, started from
        <start_point> and switch to it.  The first commit made on this
@@@ -213,42 -204,140 +213,140 @@@ leave out at most one of `A` and `B`, i
  
  
  
 -Detached HEAD
 +DETACHED HEAD
  -------------
+ HEAD normally refers to a named branch (e.g. 'master'). Meanwhile, each
+ branch refers to a specific commit. Let's look at a repo with three
+ commits, one of them tagged, and with branch 'master' checked out:
  
- It is sometimes useful to be able to 'checkout' a commit that is
- not at the tip of one of your branches.  The most obvious
- example is to check out the commit at a tagged official release
- point, like this:
+ ------------
+          HEAD (refers to branch 'master')
+           |
+           v
+ a---b---c  branch 'master' (refers to commit 'c')
+     ^
+     |
+   tag 'v2.0' (refers to commit 'b')
+ ------------
+ When a commit is created in this state, the branch is updated to refer to
+ the new commit. Specifically, 'git commit' creates a new commit 'd', whose
+ parent is commit 'c', and then updates branch 'master' to refer to new
+ commit 'd'. HEAD still refers to branch 'master' and so indirectly now refers
+ to commit 'd':
  
  ------------
- $ git checkout v2.6.18
+ $ edit; git add; git commit
+              HEAD (refers to branch 'master')
+               |
+               v
+ a---b---c---d  branch 'master' (refers to commit 'd')
+     ^
+     |
+   tag 'v2.0' (refers to commit 'b')
  ------------
  
- Earlier versions of git did not allow this and asked you to
- create a temporary branch using the `-b` option, but starting from
- version 1.5.0, the above command 'detaches' your HEAD from the
- current branch and directly points at the commit named by the tag
- (`v2.6.18` in the example above).
- You can use all git commands while in this state.  You can use
- `git reset --hard $othercommit` to further move around, for
- example.  You can make changes and create a new commit on top of
- a detached HEAD.  You can even create a merge by using `git
- merge $othercommit`.
- The state you are in while your HEAD is detached is not recorded
- by any branch (which is natural --- you are not on any branch).
- What this means is that you can discard your temporary commits
- and merges by switching back to an existing branch (e.g. `git
- checkout master`), and a later `git prune` or `git gc` would
- garbage-collect them.  If you did this by mistake, you can ask
- the reflog for HEAD where you were, e.g.
+ 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' (here we show two ways this may be done):
  
  ------------
- $ git log -g -2 HEAD
+ $ git checkout v2.0  # or
+ $ git checkout master^^
+    HEAD (refers to commit 'b')
+     |
+     v
+ a---b---c---d  branch 'master' (refers to commit 'd')
+     ^
+     |
+   tag 'v2.0' (refers to commit 'b')
+ ------------
+ Notice that regardless of which checkout command we use, HEAD now refers
+ directly to commit 'b'. This is known as being in detached HEAD state.
+ It means simply that HEAD refers to a specific commit, as opposed to
+ referring to a named branch. Let's see what happens when we create a commit:
  ------------
+ $ edit; git add; git commit
+      HEAD (refers to commit 'e')
+       |
+       v
+       e
+      /
+ a---b---c---d  branch 'master' (refers to commit 'd')
+     ^
+     |
+   tag 'v2.0' (refers to commit 'b')
+ ------------
+ There is now a new commit 'e', but it is referenced only by HEAD. We can
+ of course add yet another commit in this state:
  
+ ------------
+ $ edit; git add; git commit
+        HEAD (refers to commit 'f')
+         |
+         v
+       e---f
+      /
+ a---b---c---d  branch 'master' (refers to commit 'd')
+     ^
+     |
+   tag 'v2.0' (refers to commit 'b')
+ ------------
+ 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
+              HEAD (refers to branch 'master')
+       e---f     |
+      /          v
+ a---b---c---d  branch 'master' (refers to commit 'd')
+     ^
+     |
+   tag 'v2.0' (refers to commit 'b')
+ ------------
+ It is important to realize that at this point nothing refers to commit
+ 'f'. Eventually commit 'f' (and by extension commit 'e') 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 commit 'f', and then
+ updates HEAD to refer to branch 'foo'. In other words, we'll no longer
+ be in detached HEAD state after this command.
+ <2> similarly creates a new branch 'foo', which refers to commit 'f',
+ but leaves HEAD detached.
+ <3> creates a new tag 'foo', which refers to commit 'f',
+ leaving HEAD detached.
+ If we have moved away from commit 'f', then we must first recover its object
+ name (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 either of these commands:
+ ------------
+ $ git reflog -2 HEAD # or
+ $ git log -g -2 HEAD
+ ------------
  
  EXAMPLES
  --------