{"thread":{"id":"26537","subject":"[PATCH] git-checkout.txt: improve detached HEAD documentation","startedAt":"2011-02-17T19:46:06Z","lastAt":"2011-02-22T15:19:03Z","messageCount":9,"participants":["Jay Soffian","Nicolas Pitre","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"161440","messageId":"1297971966-58500-1-git-send-email-jaysoffian@gmail.com","threadId":"26537","inReplyTo":null,"subject":"[PATCH] git-checkout.txt: improve detached HEAD documentation","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-02-17T19:46:06Z","receivedAt":"2011-02-17T19:46:06Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"The detached HEAD state is a source of much confusion for users\nnew to git. Here we try to document it better.\n\nReworked from http://article.gmane.org/gmane.comp.version-control.git/138440\n\nRequested-by: Nicolas Pitre <nico@fluxnic.net>\nSigned-off-by: Jay Soffian <jaysoffian@gmail.com>\n---\nNicolas only asked me to contribute this a full year ago, not too\nbad. :)\n\n Documentation/git-checkout.txt |  108 +++++++++++++++++++++++++++++++---------\n 1 files changed, 85 insertions(+), 23 deletions(-)\n\ndiff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\nindex 880763d..21abd2a 100644\n--- a/Documentation/git-checkout.txt\n+++ b/Documentation/git-checkout.txt\n@@ -206,40 +206,102 @@ leave out at most one of `A` and `B`, in which case it defaults to `HEAD`.\n \n Detached HEAD\n -------------\n+HEAD normally refers to a named branch (e.g. \"master\"). Meanwhile, each\n+branch refers to a specific commit-id. Let's look at a repo with three\n+commits and with \"master\" checked out:\n \n-It is sometimes useful to be able to 'checkout' a commit that is\n-not at the tip of one of your branches.  The most obvious\n-example is to check out the commit at a tagged official release\n-point, like this:\n+------------\n+           HEAD (refers to master)\n+            v\n+a---b---c  master (refers to c)\n+------------\n+\n+When a commit is created in this state, the branch is updated to the new\n+commit-id. Let's add a commit:\n \n ------------\n-$ git checkout v2.6.18\n+               HEAD (refers to master)\n+                v\n+a---b---c---d  master (refers to d)\n ------------\n \n-Earlier versions of git did not allow this and asked you to\n-create a temporary branch using the `-b` option, but starting from\n-version 1.5.0, the above command 'detaches' your HEAD from the\n-current branch and directly points at the commit named by the tag\n-(`v2.6.18` in the example above).\n+It is sometimes useful to be able to checkout a commit that is not at\n+the tip of any named branch, or even to create a new commit that is not\n+referenced by a named branch. Let's look at what happens when we\n+checkout commit b:\n \n-You can use all git commands while in this state.  You can use\n-`git reset --hard $othercommit` to further move around, for\n-example.  You can make changes and create a new commit on top of\n-a detached HEAD.  You can even create a merge by using `git\n-merge $othercommit`.\n+------------\n+$ git checkout master^^\n \n-The state you are in while your HEAD is detached is not recorded\n-by any branch (which is natural --- you are not on any branch).\n-What this means is that you can discard your temporary commits\n-and merges by switching back to an existing branch (e.g. `git\n-checkout master`), and a later `git prune` or `git gc` would\n-garbage-collect them.  If you did this by mistake, you can ask\n-the reflog for HEAD where you were, e.g.\n+   HEAD (refers to b)\n+    v\n+a---b---c---d  master (refers to d)\n+------------\n+\n+Notice that HEAD now refers directly to commit b. In git terminology,\n+this is known as having a detached HEAD. It means simply that HEAD\n+refers to a specific commit-id, as opposed to referring to a named\n+branch. Let's add a commit while HEAD is detached:\n \n ------------\n-$ git log -g -2 HEAD\n+     HEAD (refers to e)\n+      v\n+      e\n+     /\n+a---b---c---d  master (refers to d)\n+------------\n+\n+We have created a new commit, but it is referenced only by HEAD. We can\n+of course add yet another commit in this state:\n+\n+------------\n+         HEAD (refers to f)\n+          v\n+      e---f\n+     /\n+a---b---c---d  master (refers to d)\n+------------\n+\n+In fact, we can perform all the normal git operations. But, let's look\n+at what happens when we then checkout master:\n+\n ------------\n+$ git checkout master\n \n+      e---f    HEAD (refers to master)\n+     /          v\n+a---b---c---d  master (refers to d)\n+------------\n+\n+It is important to realize that at this point nothing refers to commits\n+e and f. Eventually these commits will be deleted by the routine git\n+garbage collection process, unless we create a reference before that\n+happens. If we have not yet moved away from commit f, any of these will\n+create a reference to it:\n+\n+------------\n+$ git checkout -b foo # (1)\n+$ git branch foo      # (2)\n+$ git tag foo         # (3)\n+------------\n+\n+(1) creates a new branch \"foo\", which refers to f, and then updates HEAD\n+to refer to \"foo\". In other words, we'll no longer be in detached HEAD\n+state after (1).\n+\n+(2) similarly creates a new branch \"foo\", which refers to f, but leaves\n+HEAD detached.\n+\n+(3) creates a new tag \"foo\", which refers to f, leaving HEAD detached.\n+\n+If we have moved away from commit f, then we must first recover its id\n+(typically by using git reflog), and then we can create a reference to\n+it. For example, to see the last two commits to which HEAD referred, we\n+can use:\n+\n+------------\n+$ git log -g -2 HEAD\n+------------\n \n EXAMPLES\n --------\n-- \n1.7.4.1.29.g21713\n"},{"id":"161441","messageId":"AANLkTi=tp2KasvPxSsHgQp3DqEHfMX6w+re7s+UYPVJ+@mail.gmail.com","threadId":"26537","inReplyTo":"1297971966-58500-1-git-send-email-jaysoffian@gmail.com","subject":"Re: [PATCH] git-checkout.txt: improve detached HEAD documentation","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-02-17T19:48:33Z","receivedAt":"2011-02-17T19:48:33Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Thu, Feb 17, 2011 at 2:46 PM, Jay Soffian <jaysoffian@gmail.com> wrote:\n> The detached HEAD state is a source of much confusion for users\n> new to git. Here we try to document it better.\n>\n> Reworked from http://article.gmane.org/gmane.comp.version-control.git/138440\n\nThe patch may be difficult to read, so here's the man output after\napplying the patch:\n\nDETACHED HEAD\n       HEAD normally refers to a named branch (e.g. \"master\"). Meanwhile, each\n       branch refers to a specific commit-id. Let's look at a repo with three\n       commits and with \"master\" checked out:\n\n                      HEAD (refers to master)\n                       v\n           a---b---c  master (refers to c)\n\n       When a commit is created in this state, the branch is updated to the\n       new commit-id. Let's add a commit:\n\n                          HEAD (refers to master)\n                           v\n           a---b---c---d  master (refers to d)\n\n       It is sometimes useful to be able to checkout a commit that is not at\n       the tip of any named branch, or even to create a new commit that is not\n       referenced by a named branch. Let's look at what happens when we\n       checkout commit b:\n\n           $ git checkout master^^\n\n              HEAD (refers to b)\n               v\n           a---b---c---d  master (refers to d)\n\n       Notice that HEAD now refers directly to commit b. In git terminology,\n       this is known as having a detached HEAD. It means simply that HEAD\n       refers to a specific commit-id, as opposed to referring to a named\n       branch. Let's add a commit while HEAD is detached:\n\n                HEAD (refers to e)\n                 v\n                 e\n                /\n           a---b---c---d  master (refers to d)\n\n       We have created a new commit, but it is referenced only by HEAD. We can\n       of course add yet another commit in this state:\n\n                    HEAD (refers to f)\n                     v\n                 e---f\n                /\n           a---b---c---d  master (refers to d)\n\n       In fact, we can perform all the normal git operations. But, let's look\n       at what happens when we then checkout master:\n\n           $ git checkout master\n\n                 e---f    HEAD (refers to master)\n                /          v\n           a---b---c---d  master (refers to d)\n\n       It is important to realize that at this point nothing refers to commits\n       e and f. Eventually these commits will be deleted by the routine git\n       garbage collection process, unless we create a reference before that\n       happens. If we have not yet moved away from commit f, any of these will\n       create a reference to it:\n\n           $ git checkout -b foo # (1)\n           $ git branch foo      # (2)\n           $ git tag foo         # (3)\n\n       (1) creates a new branch \"foo\", which refers to f, and then updates\n       HEAD to refer to \"foo\". In other words, we'll no longer be in detached\n       HEAD state after (1).\n\n       (2) similarly creates a new branch \"foo\", which refers to f, but leaves\n       HEAD detached.\n\n       (3) creates a new tag \"foo\", which refers to f, leaving HEAD detached.\n\n       If we have moved away from commit f, then we must first recover its id\n       (typically by using git reflog), and then we can create a reference to\n       it. For example, to see the last two commits to which HEAD referred, we\n       can use:\n\n           $ git log -g -2 HEAD\n"},{"id":"161451","messageId":"alpine.LFD.2.00.1102171545331.14920@xanadu.home","threadId":"26537","inReplyTo":"1297971966-58500-1-git-send-email-jaysoffian@gmail.com","subject":"Re: [PATCH] git-checkout.txt: improve detached HEAD documentation","fromName":"Nicolas Pitre","fromEmail":"nico@fluxnic.net","sentAt":"2011-02-17T20:47:11Z","receivedAt":"2011-02-17T20:47:11Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Thu, 17 Feb 2011, Jay Soffian wrote:\n\n> The detached HEAD state is a source of much confusion for users\n> new to git. Here we try to document it better.\n> \n> Reworked from http://article.gmane.org/gmane.comp.version-control.git/138440\n\nExcellent!\n\n> Requested-by: Nicolas Pitre <nico@fluxnic.net>\n> Signed-off-by: Jay Soffian <jaysoffian@gmail.com>\n\nAcked-by: Nicolas Pitre <nico@fluxnic.net>\n\n> ---\n> Nicolas only asked me to contribute this a full year ago, not too\n> bad. :)\n\nBetter late than never.\n\n>  Documentation/git-checkout.txt |  108 +++++++++++++++++++++++++++++++---------\n>  1 files changed, 85 insertions(+), 23 deletions(-)\n> \n> diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\n> index 880763d..21abd2a 100644\n> --- a/Documentation/git-checkout.txt\n> +++ b/Documentation/git-checkout.txt\n> @@ -206,40 +206,102 @@ leave out at most one of `A` and `B`, in which case it defaults to `HEAD`.\n>  \n>  Detached HEAD\n>  -------------\n> +HEAD normally refers to a named branch (e.g. \"master\"). Meanwhile, each\n> +branch refers to a specific commit-id. Let's look at a repo with three\n> +commits and with \"master\" checked out:\n>  \n> -It is sometimes useful to be able to 'checkout' a commit that is\n> -not at the tip of one of your branches.  The most obvious\n> -example is to check out the commit at a tagged official release\n> -point, like this:\n> +------------\n> +           HEAD (refers to master)\n> +            v\n> +a---b---c  master (refers to c)\n> +------------\n> +\n> +When a commit is created in this state, the branch is updated to the new\n> +commit-id. Let's add a commit:\n>  \n>  ------------\n> -$ git checkout v2.6.18\n> +               HEAD (refers to master)\n> +                v\n> +a---b---c---d  master (refers to d)\n>  ------------\n>  \n> -Earlier versions of git did not allow this and asked you to\n> -create a temporary branch using the `-b` option, but starting from\n> -version 1.5.0, the above command 'detaches' your HEAD from the\n> -current branch and directly points at the commit named by the tag\n> -(`v2.6.18` in the example above).\n> +It is sometimes useful to be able to checkout a commit that is not at\n> +the tip of any named branch, or even to create a new commit that is not\n> +referenced by a named branch. Let's look at what happens when we\n> +checkout commit b:\n>  \n> -You can use all git commands while in this state.  You can use\n> -`git reset --hard $othercommit` to further move around, for\n> -example.  You can make changes and create a new commit on top of\n> -a detached HEAD.  You can even create a merge by using `git\n> -merge $othercommit`.\n> +------------\n> +$ git checkout master^^\n>  \n> -The state you are in while your HEAD is detached is not recorded\n> -by any branch (which is natural --- you are not on any branch).\n> -What this means is that you can discard your temporary commits\n> -and merges by switching back to an existing branch (e.g. `git\n> -checkout master`), and a later `git prune` or `git gc` would\n> -garbage-collect them.  If you did this by mistake, you can ask\n> -the reflog for HEAD where you were, e.g.\n> +   HEAD (refers to b)\n> +    v\n> +a---b---c---d  master (refers to d)\n> +------------\n> +\n> +Notice that HEAD now refers directly to commit b. In git terminology,\n> +this is known as having a detached HEAD. It means simply that HEAD\n> +refers to a specific commit-id, as opposed to referring to a named\n> +branch. Let's add a commit while HEAD is detached:\n>  \n>  ------------\n> -$ git log -g -2 HEAD\n> +     HEAD (refers to e)\n> +      v\n> +      e\n> +     /\n> +a---b---c---d  master (refers to d)\n> +------------\n> +\n> +We have created a new commit, but it is referenced only by HEAD. We can\n> +of course add yet another commit in this state:\n> +\n> +------------\n> +         HEAD (refers to f)\n> +          v\n> +      e---f\n> +     /\n> +a---b---c---d  master (refers to d)\n> +------------\n> +\n> +In fact, we can perform all the normal git operations. But, let's look\n> +at what happens when we then checkout master:\n> +\n>  ------------\n> +$ git checkout master\n>  \n> +      e---f    HEAD (refers to master)\n> +     /          v\n> +a---b---c---d  master (refers to d)\n> +------------\n> +\n> +It is important to realize that at this point nothing refers to commits\n> +e and f. Eventually these commits will be deleted by the routine git\n> +garbage collection process, unless we create a reference before that\n> +happens. If we have not yet moved away from commit f, any of these will\n> +create a reference to it:\n> +\n> +------------\n> +$ git checkout -b foo # (1)\n> +$ git branch foo      # (2)\n> +$ git tag foo         # (3)\n> +------------\n> +\n> +(1) creates a new branch \"foo\", which refers to f, and then updates HEAD\n> +to refer to \"foo\". In other words, we'll no longer be in detached HEAD\n> +state after (1).\n> +\n> +(2) similarly creates a new branch \"foo\", which refers to f, but leaves\n> +HEAD detached.\n> +\n> +(3) creates a new tag \"foo\", which refers to f, leaving HEAD detached.\n> +\n> +If we have moved away from commit f, then we must first recover its id\n> +(typically by using git reflog), and then we can create a reference to\n> +it. For example, to see the last two commits to which HEAD referred, we\n> +can use:\n> +\n> +------------\n> +$ git log -g -2 HEAD\n> +------------\n>  \n>  EXAMPLES\n>  --------\n> -- \n> 1.7.4.1.29.g21713\n> \n"},{"id":"161461","messageId":"7v7hcy9vrk.fsf@alter.siamese.dyndns.org","threadId":"26537","inReplyTo":"1297971966-58500-1-git-send-email-jaysoffian@gmail.com","subject":"Re: [PATCH] git-checkout.txt: improve detached HEAD documentation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-02-17T21:49:35Z","receivedAt":"2011-02-17T21:49:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jay Soffian <jaysoffian@gmail.com> writes:\n\n> diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\n> index 880763d..21abd2a 100644\n> --- a/Documentation/git-checkout.txt\n> +++ b/Documentation/git-checkout.txt\n> @@ -206,40 +206,102 @@ leave out at most one of `A` and `B`, in which case it defaults to `HEAD`.\n>  \n>  Detached HEAD\n>  -------------\n> +HEAD normally refers to a named branch (e.g. \"master\"). Meanwhile, each\n> +branch refers to a specific commit-id. Let's look at a repo with three\n\ns/commit-id/commit/; we don't say \"commit-id\" anywhere else in this\ndocument.  Also, it is Ok to be loose and colloquial in the manual and it\nis fine to say \"commit ID\" from time to time, but not in this section, one\nof the primary purpose of which is to illustrate distinction between\npointing at something that points at a commit (i.e. branch) and pointing\ndirectly at a commit (i.e. detached).\n\n> +commits and with \"master\" checked out:\n>  \n> +------------\n> +           HEAD (refers to master)\n> +            v\n> +a---b---c  master (refers to c)\n> +------------\n> +\n> +When a commit is created in this state, the branch is updated to the new\n> +commit-id. Let's add a commit:\n\n\t... updated to point the new commit. 'git commit' creates a new\n        commit 'd', makes it a child of 'c' and moves 'master' branch to\n        point at 'd'.  HEAD also points at 'd' as the result of 'master'\n        moving to the new commit.\n\nI'd also suggest avoiding \"Let's add\" and instead be more specific (see\nthe above example).\n\n>  ------------\n> +               HEAD (refers to master)\n> +                v\n> +a---b---c---d  master (refers to d)\n>  ------------\n>  \n> +It is sometimes useful to be able to checkout a commit that is not at\n> +the tip of any named branch, or even to create a new commit that is not\n> +referenced by a named branch. Let's look at what happens when we\n> +checkout commit b:\n\nI think it is a regression from the original text to omit mention of tags\nand replace the first example of the section with a more advanced use case\nof jumping to the middle of a branch; it is far more likely that a user\nwould want to detach at a specific release point.\n\nYou can rectify it by tagging 'c' as a release point and detaching the\nHEAD at that tag without losing the clarity of the following description.\nWhile doing so, it would be better to update the labels in the\nillustration with s/master/master branch/ and s/[abcde]/commit &/ as well,\ne.g.\n\n\n                   HEAD (refers to branch 'master')\n                    |\n                    V\n  a---b---c---d  branch 'master' (refers to commit 'd')\n          ^\n          |\n     tag 'v2.0' (refers to commit 'c')\n\n> +------------\n> +$ git checkout master^^\n>  \n> +   HEAD (refers to b)\n\nPerhaps s/refers/& directly/ to emphasize the difference in the\nillustration.\n\n> +    v\n> +a---b---c---d  master (refers to d)\n> +------------\n> +\n> +Notice that HEAD now refers directly to commit b. In git terminology,\n> +this is known as having a detached HEAD. It means simply that HEAD\n> +refers to a specific commit-id, as opposed to referring to a named\n> +branch. Let's add a commit while HEAD is detached:\n\nI'd suggest dropping \"In git terminology,\"; the reader knows that is what\nis being explained when he opened the documentation.\n\nWe often say \"detach the HEAD from a branch\", \"detach the HEAD at commit\n'b'\", but I don't think we say \"we have a detached HEAD\".  Same comments\nfrom a few section before apply to \"commit-id\" and \"Let's add\".\n\n    We often say \"we detach HEAD at commit 'b'\" and/or \"we detach HEAD\n    from the 'master' branch\", to describe this state.  The HEAD directly\n    points at the commit 'b', as opposed to referring to it indirectly\n    through the \"current\" branch it points at.  From this state, 'git\n    commit' will create a new commit 'e', makes it a child of 'b', and\n    moves HEAD to directly point at it.\n\n> +$ git checkout master\n>  \n> +      e---f    HEAD (refers to master)\n> +     /          v\n> +a---b---c---d  master (refers to d)\n> +------------\n> +\n> +It is important to realize that at this point nothing refers to commits\n> +e and f. Eventually these commits will be deleted by the routine git\n> +garbage collection process, unless we create a reference before that\n> +happens. If we have not yet moved away from commit f, any of these will\n> +create a reference to it:\n> +\n> +------------\n> +$ git checkout -b foo # (1)\n> +$ git branch foo      # (2)\n> +$ git tag foo         # (3)\n> +------------\n> +\n> +(1) creates a new branch \"foo\", which refers to f, and then updates HEAD\n> +to refer to \"foo\". In other words, we'll no longer be in detached HEAD\n> +state after (1).\n\nSomehow it feels funny to say \"after (1)\" in the section marked as such.\n\"after doing so\", perhaps?\n\nAlso mimick the way how git-reset.txt, everyday.txt etc. tell AsciiDoc to\nproduce pretty labels that refer to parts in an illustration, with <1>,\n<2>, etc.\n\n> +If we have moved away from commit f, then we must first recover its id\n\ns/id/object name/;\n\nOther than these three points, the description from \"It is important\" up\nto this point looks good.\n\n> +(typically by using git reflog), and then we can create a reference to\n> +it. For example, to see the last two commits to which HEAD referred, we\n> +can use:\n> +\n> +------------\n> +$ git log -g -2 HEAD\n> +------------\n\nA documentation written for people who do not know how to extract commit\nobject names out of reflog, it is insufficient to give the command line\nexample without giving a few lines of example output.  Instead of \"log -g\",\nit probably is easier to use \"git reflog -2\" for this purpose.\n\nThanks.\n"},{"id":"161471","messageId":"alpine.LFD.2.00.1102171909412.14920@xanadu.home","threadId":"26537","inReplyTo":"7v7hcy9vrk.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] git-checkout.txt: improve detached HEAD documentation","fromName":"Nicolas Pitre","fromEmail":"nico@fluxnic.net","sentAt":"2011-02-18T00:14:25Z","receivedAt":"2011-02-18T00:14:25Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Thu, 17 Feb 2011, Junio C Hamano wrote:\n\n> Jay Soffian <jaysoffian@gmail.com> writes:\n> \n> > +It is sometimes useful to be able to checkout a commit that is not at\n> > +the tip of any named branch, or even to create a new commit that is not\n> > +referenced by a named branch. Let's look at what happens when we\n> > +checkout commit b:\n> \n> I think it is a regression from the original text to omit mention of tags\n> and replace the first example of the section with a more advanced use case\n> of jumping to the middle of a branch; it is far more likely that a user\n> would want to detach at a specific release point.\n> \n> You can rectify it by tagging 'c' as a release point and detaching the\n> HEAD at that tag without losing the clarity of the following description.\n> While doing so, it would be better to update the labels in the\n> illustration with s/master/master branch/ and s/[abcde]/commit &/ as well,\n> e.g.\n> \n> \n>                    HEAD (refers to branch 'master')\n>                     |\n>                     V\n>   a---b---c---d  branch 'master' (refers to commit 'd')\n>           ^\n>           |\n>      tag 'v2.0' (refers to commit 'c')\n\nWhile I agree with the above, I think this is still a good idea to keep \nthis example using a non-tagged commit as well.  Perhaps not the first \none as you say.\n\n\nNicolas\n"},{"id":"161474","messageId":"7vmxlu89z1.fsf@alter.siamese.dyndns.org","threadId":"26537","inReplyTo":"alpine.LFD.2.00.1102171909412.14920@xanadu.home","subject":"Re: [PATCH] git-checkout.txt: improve detached HEAD documentation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-02-18T00:25:38Z","receivedAt":"2011-02-18T00:25:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nicolas Pitre <nico@fluxnic.net> writes:\n\n> On Thu, 17 Feb 2011, Junio C Hamano wrote:\n> ...\n>> You can rectify it by tagging 'c' as a release point and detaching the\n>> HEAD at that tag without losing the clarity of the following description.\n>> While doing so, it would be better to update the labels in the\n>> illustration with s/master/master branch/ and s/[abcde]/commit &/ as well,\n>> e.g.\n>> \n>> \n>>                    HEAD (refers to branch 'master')\n>>                     |\n>>                     V\n>>   a---b---c---d  branch 'master' (refers to commit 'd')\n>>           ^\n>>           |\n>>      tag 'v2.0' (refers to commit 'c')\n>\n> While I agree with the above, I think this is still a good idea to keep \n> this example using a non-tagged commit as well.  Perhaps not the first \n> one as you say.\n\nJust to make sure, I wasn't opposed to the idea of showing the history\nafter building a few commits on top of the point you started from, to\nexplain why you might want to re-attach the about-to-be-orphaned commits\nto the DAG anchored by refs.\n\nIOW, detach at v2.0 tag, experiment with a few commits to fix things up,\nand then when things go well, make it a maitenance branch, or something.\n"},{"id":"161734","messageId":"1298179310-46207-1-git-send-email-jaysoffian@gmail.com","threadId":"26537","inReplyTo":"7v7hcy9vrk.fsf@alter.siamese.dyndns.org","subject":"[PATCH] git-checkout.txt: improve detached HEAD documentation","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-02-20T05:21:50Z","receivedAt":"2011-02-20T05:21:50Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"The detached HEAD state is a source of much confusion for users\nnew to git. Here we try to document it better.\n\nReworked from http://article.gmane.org/gmane.comp.version-control.git/138440\n\nRequested-by: Nicolas Pitre <nico@fluxnic.net>\nSigned-off-by: Jay Soffian <jaysoffian@gmail.com>\n---\nIncorporated Junio's feedback. Though this is a bit clearer, I think it's\nstarting to make the man page quite long due to the taller ascii\nart (adding the tag plus the stem to the arrows adds 4 lines to each\npicture).\n\nI don't have any more time to allocate to this patch. I think it's a vast\nimprovement as is, and you should feel free to make any corrections/edits you\nsee fit so that it may be applied.\n\n Documentation/git-checkout.txt |  145 +++++++++++++++++++++++++++++++++------\n 1 files changed, 122 insertions(+), 23 deletions(-)\n\ndiff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\nindex 880763d..8a252dc 100644\n--- a/Documentation/git-checkout.txt\n+++ b/Documentation/git-checkout.txt\n@@ -206,40 +206,139 @@ leave out at most one of `A` and `B`, in which case it defaults to `HEAD`.\n \n Detached HEAD\n -------------\n+HEAD normally refers to a named branch (e.g. 'master'). Meanwhile, each\n+branch refers to a specific commit. Let's look at a repo with three\n+commits, one of them tagged, and with branch 'master' checked out:\n \n-It is sometimes useful to be able to 'checkout' a commit that is\n-not at the tip of one of your branches.  The most obvious\n-example is to check out the commit at a tagged official release\n-point, like this:\n+------------\n+           HEAD (refers to branch 'master')\n+            |\n+            v\n+a---b---c  branch 'master' (refers to commit 'c')\n+    ^\n+    |\n+  tag 'v2.0' (refers to commit 'b')\n+------------\n+\n+When a commit is created in this state, the branch is updated to refer to\n+the new commit. Specifically, 'git commit' creates a new commit 'd', whose\n+parent is commit 'c', and then updates branch 'master' to refer to new\n+commit 'd'. HEAD still refers to branch 'master' and so indirectly now refers\n+to commit 'd':\n \n ------------\n-$ git checkout v2.6.18\n+$ edit; git add; git commit\n+\n+               HEAD (refers to branch 'master')\n+                |\n+                v\n+a---b---c---d  branch 'master' (refers to commit 'd')\n+    ^\n+    |\n+  tag 'v2.0' (refers to commit 'b')\n ------------\n \n-Earlier versions of git did not allow this and asked you to\n-create a temporary branch using the `-b` option, but starting from\n-version 1.5.0, the above command 'detaches' your HEAD from the\n-current branch and directly points at the commit named by the tag\n-(`v2.6.18` in the example above).\n+It is sometimes useful to be able to checkout a commit that is not at\n+the tip of any named branch, or even to create a new commit that is not\n+referenced by a named branch. Let's look at what happens when we\n+checkout commit 'b' (here we show three ways this may be done):\n \n-You can use all git commands while in this state.  You can use\n-`git reset --hard $othercommit` to further move around, for\n-example.  You can make changes and create a new commit on top of\n-a detached HEAD.  You can even create a merge by using `git\n-merge $othercommit`.\n+------------\n+$ git checkout v2.0  # or\n+$ git checkout b     # or\n+$ git checkout master^^\n+\n+   HEAD (refers to commit 'b')\n+    |\n+    v\n+a---b---c---d  branch 'master' (refers to commit 'd')\n+    ^\n+    |\n+  tag 'v2.0' (refers to commit 'b')\n+------------\n \n-The state you are in while your HEAD is detached is not recorded\n-by any branch (which is natural --- you are not on any branch).\n-What this means is that you can discard your temporary commits\n-and merges by switching back to an existing branch (e.g. `git\n-checkout master`), and a later `git prune` or `git gc` would\n-garbage-collect them.  If you did this by mistake, you can ask\n-the reflog for HEAD where you were, e.g.\n+Notice that regardless of which checkout command we use, HEAD now refers\n+directly to commit 'b'. This is known as being in detached HEAD state.\n+It means simply that HEAD refers to a specific commit, as opposed to\n+referring to a named branch. Let's see what happens when we create a commit:\n \n ------------\n-$ git log -g -2 HEAD\n+$ edit; git add; git commit\n+\n+     HEAD (refers to commit 'e')\n+      |\n+      v\n+      e\n+     /\n+a---b---c---d  branch 'master' (refers to commit 'd')\n+    ^\n+    |\n+  tag 'v2.0' (refers to commit 'b')\n ------------\n \n+There is now a new commit 'e', but it is referenced only by HEAD. We can\n+of course add yet another commit in this state:\n+\n+------------\n+$ edit; git add; git commit\n+\n+         HEAD (refers to commit 'f')\n+          |\n+          v\n+      e---f\n+     /\n+a---b---c---d  branch 'master' (refers to commit 'd')\n+    ^\n+    |\n+  tag 'v2.0' (refers to commit 'b')\n+------------\n+\n+In fact, we can perform all the normal git operations. But, let's look\n+at what happens when we then checkout master:\n+\n+------------\n+$ git checkout master\n+\n+               HEAD (refers to branch 'master')\n+      e---f     |\n+     /          v\n+a---b---c---d  branch 'master' (refers to commit 'd')\n+    ^\n+    |\n+  tag 'v2.0' (refers to commit 'b')\n+------------\n+\n+It is important to realize that at this point nothing refers to commit\n+'f'. Eventually commit 'f' (and by extension commit 'e') will be deleted\n+by the routine git garbage collection process, unless we create a reference\n+before that happens. If we have not yet moved away from commit 'f',\n+any of these will create a reference to it:\n+\n+------------\n+$ git checkout -b foo   <1>\n+$ git branch foo        <2>\n+$ git tag foo           <3>\n+------------\n+\n+<1> creates a new branch 'foo', which refers to commit 'f', and then\n+updates HEAD to refer to branch 'foo'. In other words, we'll no longer\n+be in detached HEAD state after this command.\n+\n+<2> similarly creates a new branch 'foo', which refers to commit 'f',\n+but leaves HEAD detached.\n+\n+<3> creates a new tag 'foo', which refers to commit 'f',\n+leaving HEAD detached.\n+\n+If we have moved away from commit 'f', then we must first recover its object\n+name (typically by using git reflog), and then we can create a reference to\n+it. For example, to see the last two commits to which HEAD referred, we\n+can use either of these commands:\n+\n+------------\n+$ git reflog -2 HEAD # or\n+$ git log -g -2 HEAD\n+------------\n \n EXAMPLES\n --------\n-- \n1.7.4.1.52.g8e1b\n"},{"id":"161858","messageId":"7vd3mkfw8w.fsf@alter.siamese.dyndns.org","threadId":"26537","inReplyTo":"1298179310-46207-1-git-send-email-jaysoffian@gmail.com","subject":"Re: [PATCH] git-checkout.txt: improve detached HEAD documentation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-02-22T05:56:15Z","receivedAt":"2011-02-22T05:56:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jay Soffian <jaysoffian@gmail.com> writes:\n\n> +It is sometimes useful to be able to checkout a commit that is not at\n> +the tip of any named branch, or even to create a new commit that is not\n> +referenced by a named branch. Let's look at what happens when we\n> +checkout commit 'b' (here we show three ways this may be done):\n>  \n> +------------\n> +$ git checkout v2.0  # or\n> +$ git checkout b     # or\n> +$ git checkout master^^\n\nI'd drop the second one, as \"b\" is not something the end user would type\nfrom the command line (you could say \"b's commit ID\" but the string 'b' is\nnot it, unless it is a tag or something, in which case the first one that\nuses 'v2.0' already illustrates it), and adjust \"three\" accordingly.\n\nOther than that, I think this version is a vast improvement over what we\nhave.\n\nThanks.\n"},{"id":"161883","messageId":"AANLkTimG885yeidetLTNyDUiuNmEMhfZcNkvXSNbOHD=@mail.gmail.com","threadId":"26537","inReplyTo":"7vd3mkfw8w.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] git-checkout.txt: improve detached HEAD documentation","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-02-22T15:19:03Z","receivedAt":"2011-02-22T15:19:03Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Tue, Feb 22, 2011 at 12:56 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Jay Soffian <jaysoffian@gmail.com> writes:\n>\n>> +It is sometimes useful to be able to checkout a commit that is not at\n>> +the tip of any named branch, or even to create a new commit that is not\n>> +referenced by a named branch. Let's look at what happens when we\n>> +checkout commit 'b' (here we show three ways this may be done):\n>>\n>> +------------\n>> +$ git checkout v2.0  # or\n>> +$ git checkout b     # or\n>> +$ git checkout master^^\n>\n> I'd drop the second one, as \"b\" is not something the end user would type\n> from the command line (you could say \"b's commit ID\" but the string 'b' is\n> not it, unless it is a tag or something, in which case the first one that\n> uses 'v2.0' already illustrates it)\n\nAh, in my mind, b _is_ the commit-ID. In your mind, b is the commit.\nFair enough, drop it.\n\n> and adjust \"three\" accordingly. Other than that, I think this version is\n> a vast improvement over what we have.\n\nWould you mind amending what you've got so I don't have to resend?\n\nThanks,\n\nj.\n"}]}