{"thread":{"id":"66484","subject":"[PATCH] doc: checkout: rewrite detached HEAD state explanation","startedAt":"2026-10-07T14:52:01Z","lastAt":"2026-10-07T19:02:30Z","messageCount":3,"participants":["Julia Evans via GitGitGadget","Junio C Hamano","Kristoffer Haugsbakk"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"554386","messageId":"pull.2250.git.1791384721919.gitgitgadget@gmail.com","threadId":"66484","inReplyTo":null,"subject":"[PATCH] doc: checkout: rewrite detached HEAD state explanation","fromName":"Julia Evans via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-10-07T14:52:01Z","receivedAt":"2026-10-07T14:52:01Z","isPatch":true,"sender":{"key":"julia@jvns.ca","avatar":"https://avatars.githubusercontent.com/u/817739?v=4"},"body":"From: Julia Evans <julia@jvns.ca>\n\nThe current explanation has the following issues:\n\n- Says detached HEAD state is useful but doesn't explain why\n- Takes many paragraphs before explaining what detached HEAD state is\n- It's common for users to accidentally end up in detached HEAD state,\n  but it doesn't explain why that might happen\n- One of the UI improvements in `git switch` is to make it harder\n  to detach accidentally, but that isn't advertised.\n  See 7968bef06b (switch: only allow explicit detached HEAD, 2019-03-29)\n- Too many confusing diagrams\n\nWrite a new explanation addressing these issues, and put it in a\nstandalone guide so that we can easily reference it from advice\n(\"see `git help detachedhead`\").\nThe result is a shorter guide that covers more material.\n\nThe framing that \"Git considers commits that aren't on a branch/other\nreference to be garbage\" is taken from Steve Klabnik's tutorial\nhttps://steveklabnik.github.io/jujutsu-tutorial/branching-merging-and-conflicts/anonymous-branches.html.\nIt's funny and it's consistent with the way Git uses the term\n\"garbage collection\".\n\nCo-authored-by: Marie Claire LeBlanc Flanagan <hello@marieflanagan.com>\nSigned-off-by: Julia Evans <julia@jvns.ca>\n---\n    doc: checkout: rewrite detached HEAD state explanation\n    \n    Often when rewriting these explanations I go through a process where I\n    ask users' feedback on the old explanation. Here I didn't do that\n    basically because that process takes a long time and I'm working on a\n    bunch of other time consuming docs projects so I did a quick rewrite\n    based on my previous experience explaining detached HEAD state to folks.\n    \n    I thought this could be a nice quick docs win on a topic which many\n    users find quite confusing. If the changes here are too controversial I\n    can drop it for now.\n    \n    Also if folks object to making a separate git help detachedhead guide\n    I'm happy to drop that too. Personally I'm excited about the idea of\n    being able to reference the guides in our advice (which is one of our\n    best tools for getting users info about how to use Git!), but it's not\n    possible to let users jump to a subsection, so this is sort of a hack\n    around that.\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-2250%2Fjvns%2Fdetached-head-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2250/jvns/detached-head-v1\nPull-Request: https://github.com/gitgitgadget/git/pull/2250\n\n Documentation/detached-head.adoc   |  43 ++++++++++\n Documentation/git-checkout.adoc    | 129 +----------------------------\n Documentation/gitdetachedhead.adoc |  14 ++++\n advice.c                           |   1 +\n command-list.txt                   |   1 +\n 5 files changed, 60 insertions(+), 128 deletions(-)\n create mode 100644 Documentation/detached-head.adoc\n create mode 100644 Documentation/gitdetachedhead.adoc\n\ndiff --git a/Documentation/detached-head.adoc b/Documentation/detached-head.adoc\nnew file mode 100644\nindex 0000000000..1e00712124\n--- /dev/null\n+++ b/Documentation/detached-head.adoc\n@@ -0,0 +1,43 @@\n+`HEAD` is where Git stores your current branch. `HEAD` can either be:\n+\n+1. A branch, which is your current branch.\n+2. A commit ID, when you don't have a current branch.\n+   This is called \"detached HEAD state\".\n+\n+It can sometimes be useful for `HEAD` to be a commit ID.\n+For example, it lets you look at an old version of your code\n+(with `git checkout COMMIT_ID`).\n+\n+The only problem is that if you create new commits while in detached\n+HEAD state, those commits won't be on a branch. This makes those new\n+commits much harder to find later. Also, Git considers commits that\n+aren't on any branch (or a tag or other reference) to be garbage.\n+Git will eventually permanently delete those \"garbage\" commits during\n+garbage collection.\n+\n+There are 3 main ways you can end up in detached HEAD state\n+unintentionally:\n+\n+1. `git checkout COMMIT_ID`, where `COMMIT_ID` is a commit ID\n+2. `git checkout v1.3`, where v1.3 is a tag name\n+3. `git checkout origin/main`, where `origin/main` is\n+   a remote-tracking branch\n+\n+Checking out a tag puts you in detached HEAD state because `HEAD` can\n+only be a branch or a commit, not a tag or any other reference.\n+So `git checkout TAG` will set HEAD to the commit for that tag.\n+\n+The easiest way to avoid accidentally ending up in detached HEAD state\n+is to use linkgit:git-switch[1] instead of linkgit:git-checkout[1] to\n+switch branches. `git switch` won't let you detach unless you explicitly\n+pass the `--detach` argument.\n+\n+To get back onto a branch, you can:\n+\n+1. Switch to the branch you want to be on, with `git switch BRANCHNAME`.\n+2. Create a new branch at the current commit, with `git switch -c BRANCHNAME`.\n+   You might want to do this if you've created new commits, so that you can\n+   find the commit later and so that it won't be garbage collected.\n+\n+If you create commits in detached HEAD state that aren't on a branch,\n+you can find them later using linkgit:git-reflog[1].\ndiff --git a/Documentation/git-checkout.adoc b/Documentation/git-checkout.adoc\nindex 2aefea0228..4e9e94e24d 100644\n--- a/Documentation/git-checkout.adoc\n+++ b/Documentation/git-checkout.adoc\n@@ -376,135 +376,8 @@ For more details, see the 'pathspec' entry in linkgit:gitglossary[7].\n [[DETACHED_HEAD]]\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-------------\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-$ 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-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 two ways this may be done):\n-\n-------------\n-$ git checkout v2.0  # 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-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-$ 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-\t HEAD (refers to commit 'f')\n-\t  |\n-\t  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  # or \"git switch -c foo\"  <1>\n-$ git branch foo                                 <2>\n-$ git tag foo                                    <3>\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-<2> similarly creates a new branch `foo`, which refers to commit `f`,\n-    but leaves `HEAD` detached.\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+include::detached-head.adoc[]\n \n [[ARGUMENT_DISAMBIGUATION]]\n ARGUMENT DISAMBIGUATION\ndiff --git a/Documentation/gitdetachedhead.adoc b/Documentation/gitdetachedhead.adoc\nnew file mode 100644\nindex 0000000000..0aeecd159c\n--- /dev/null\n+++ b/Documentation/gitdetachedhead.adoc\n@@ -0,0 +1,14 @@\n+gitdetachedhead(7)\n+===============\n+\n+NAME\n+----\n+gitdetachedhead - How detached HEAD state works\n+\n+DESCRIPTION\n+-----------\n+include::detached-head.adoc[]\n+\n+GIT\n+---\n+Part of the linkgit:git[1] suite\ndiff --git a/advice.c b/advice.c\nindex 401d047391..43f86c2eaf 100644\n--- a/advice.c\n+++ b/advice.c\n@@ -291,6 +291,7 @@ void detach_advice(const char *new_name)\n \t\"\\n\"\n \t\"  git switch -\\n\"\n \t\"\\n\"\n+\t\"Run `git help detachedhead` to learn more.\\n\"\n \t\"Turn off this advice by setting config variable advice.detachedHead to false\\n\\n\");\n \n \tfprintf(stderr, fmt, new_name);\ndiff --git a/command-list.txt b/command-list.txt\nindex 63ae2a67c9..313689335f 100644\n--- a/command-list.txt\n+++ b/command-list.txt\n@@ -218,6 +218,7 @@ gitcore-tutorial                        guide\n gitcredentials                          guide\n gitcvs-migration                        guide\n gitdatamodel                            guide\n+gitdetachedhead                         guide\n gitdiffcore                             guide\n giteveryday                             guide\n gitfaq                                  guide\n\nbase-commit: 5a7d1e8045ce66c908f62598e26cbb8df7b39a90\n-- \ngitgitgadget\n\n"},{"id":"554391","messageId":"xmqqik3da2bs.fsf@gitster.g","threadId":"66484","inReplyTo":"pull.2250.git.1791384721919.gitgitgadget@gmail.com","subject":"Re: [PATCH] doc: checkout: rewrite detached HEAD state explanation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-10-07T16:43:35Z","receivedAt":"2026-10-07T16:43:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Julia Evans via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> diff --git a/Documentation/detached-head.adoc b/Documentation/detached-head.adoc\n> new file mode 100644\n> index 0000000000..1e00712124\n> --- /dev/null\n> +++ b/Documentation/detached-head.adoc\n> @@ -0,0 +1,43 @@\n> +`HEAD` is where Git stores your current branch. `HEAD` can either be:\n> +\n> +1. A branch, which is your current branch.\n> +2. A commit ID, when you don't have a current branch.\n> +   This is called \"detached HEAD state\".\n\nHEAD is branch which can either be a branch or something else?\n\n    HEAD records the state from which your current changes started.\n    This can be a branch (the \"current branch\"), or it may not be\n    associated with any concrete branch (in which case HEAD is\n    \"detached\").\n\n> +It can sometimes be useful for `HEAD` to be a commit ID.\n> +For example, it lets you look at an old version of your code\n> +(with `git checkout COMMIT_ID`).\n\nTo \"look at\" an older state is more versatile than simply running\n'git show COMMIT_ID:path', as it allows you to do anything you can\ndo on a branch, such as building and testing.  Thus,\n\n \tA detached HEAD is useful when you want to tentatively visit\n\tan old state with 'git checkout --detach v0.1', without\n\thaving to create a dedicated branch for it.\n\n> +The only problem is that if you create new commits while in detached\n> +HEAD state, those commits won't be on a branch.\n\nI would suggest rephrasing \"The only problem\" to \"One caveat is\" or\nsomething.  When sightseeing and experimenting, the ability to\ncreate throw-away commits without the need to clean them up later,\nor to invent a unique name for a temporary branch, is not a problem.\nIt is an advantage.\n\n> This makes those new\n> +commits much harder to find later. Also, Git considers commits that\n> +aren't on any branch (or a tag or other reference) to be garbage.\n> +Git will eventually permanently delete those \"garbage\" commits during\n> +garbage collection.\n\nCorrect.\n\nPerhaps it is better to clarify this by adding \"after you leave\nthe detached HEAD state\" after \"to find later\".  While you are in\nthe detached HEAD state, you can run 'git log' to find the commits\nyou created there, as you can do everything you normally can on a\nbranch, or use 'git reflog @{now}' for that matter.\n\n> +There are 3 main ways you can end up in detached HEAD state\n> +unintentionally:\n> +\n> +1. `git checkout COMMIT_ID`, where `COMMIT_ID` is a commit ID\n> +2. `git checkout v1.3`, where v1.3 is a tag name\n\nThese I wouldn't call \"unintentionally\".  They are documented and\nsupported ways to do so, and will remain to be so.  \"unknowingly\"\nmay be a more fair way to call these gotchas, though.\n\n> +3. `git checkout origin/main`, where `origin/main` is\n> +   a remote-tracking branch\n\nThis can happen when the user forgets to say \"-t\" ('git checkout -t\norigin/main' dwims to 'git checkout -t -b main origin/main'), so it\nis closer to 'unintentionally' than the above two.\n\n> +Checking out a tag puts you in detached HEAD state because `HEAD` can\n> +only be a branch or a commit, not a tag or any other reference.\n> +So `git checkout TAG` will set HEAD to the commit for that tag.\n\nCorrect.\n\n> +The easiest way to avoid accidentally ending up in detached HEAD state\n> +is to use linkgit:git-switch[1] instead of linkgit:git-checkout[1] to\n> +switch branches. `git switch` won't let you detach unless you explicitly\n> +pass the `--detach` argument.\n\nCorrect, but the motivation to 'avoid accidentally ending up' may\nwant to be spelled out.  Most often checking out a tag is to go\nsightseeing, where you do not want to 'avoid' detached HEAD.\n\n> +To get back onto a branch, you can:\n> +\n> +1. Switch to the branch you want to be on, with `git switch BRANCHNAME`.\n> +2. Create a new branch at the current commit, with `git switch -c BRANCHNAME`.\n> +   You might want to do this if you've created new commits, so that you can\n> +   find the commit later and so that it won't be garbage collected.\n\nVery good.\n\n> +If you create commits in detached HEAD state that aren't on a branch,\n> +you can find them later using linkgit:git-reflog[1].\n\nThis, as you already said, is \"much harder to find later\" option.\nThere should be a better recovery option described here before\nresorting to \"git reflog HEAD\" after you switched back.  E.g.,\n\n    If you have created commits in detached HEAD state and then\n    switched away from the state, all is not lost.  \"git checkout\"\n    would have give you a warning message, like this:\n\n\tWarning: you are leaving 2 commits behind, not connected to\n\tany of your branches\n\n\tc816689 typofix the previous\n\t8e1bff5 decsribe detached HEAD state better\n\n    You can create branches to keep them, e.g., \"git branch saved c816689\",\n    by using the commit object names left there.\n\n> diff --git a/Documentation/git-checkout.adoc b/Documentation/git-checkout.adoc\n> index 2aefea0228..4e9e94e24d 100644\n> --- a/Documentation/git-checkout.adoc\n> +++ b/Documentation/git-checkout.adoc\n> @@ -376,135 +376,8 @@ For more details, see the 'pathspec' entry in linkgit:gitglossary[7].\n>  [[DETACHED_HEAD]]\n>  DETACHED HEAD\n>  -------------\n> +include::detached-head.adoc[]\n\nLosing the diagrams is a bit concerning.  However, if the intention\nis to have readers learn how HEAD refers to a branch pointing at a\ncommit with history structured as a DAG elsewhere in a more basic\nconcepts guide, I suspect that it would actually work better.  This\ncould even be reduced to a simple \"see also\" pointer to that other\nguide.\n\nIf an existing user only uses 'switch' and never reads 'git help\ncheckout', they are already not seeing these diagrams, or perhaps\nthey learned the concepts elsewhere.  They still manage to\nunderstand Git well enough to make use of it, so perhaps this\napproach is OK.  I dunno.\n\n> diff --git a/Documentation/gitdetachedhead.adoc b/Documentation/gitdetachedhead.adoc\n> new file mode 100644\n> index 0000000000..0aeecd159c\n> --- /dev/null\n> +++ b/Documentation/gitdetachedhead.adoc\n> @@ -0,0 +1,14 @@\n> +gitdetachedhead(7)\n> +===============\n> +\n> +NAME\n> +----\n> +gitdetachedhead - How detached HEAD state works\n> +\n> +DESCRIPTION\n> +-----------\n> +include::detached-head.adoc[]\n\nThis may be good as a first step, but we may want to have more here\nthan what we show in \"git help checkout\" later.  If we miss the\npictures we lost from \"git help checkout\", it can be moved here.\n\nThanks.\n\n> +\n> +GIT\n> +---\n> +Part of the linkgit:git[1] suite\n> diff --git a/advice.c b/advice.c\n> index 401d047391..43f86c2eaf 100644\n> --- a/advice.c\n> +++ b/advice.c\n> @@ -291,6 +291,7 @@ void detach_advice(const char *new_name)\n>  \t\"\\n\"\n>  \t\"  git switch -\\n\"\n>  \t\"\\n\"\n> +\t\"Run `git help detachedhead` to learn more.\\n\"\n>  \t\"Turn off this advice by setting config variable advice.detachedHead to false\\n\\n\");\n>  \n>  \tfprintf(stderr, fmt, new_name);\n> diff --git a/command-list.txt b/command-list.txt\n> index 63ae2a67c9..313689335f 100644\n> --- a/command-list.txt\n> +++ b/command-list.txt\n> @@ -218,6 +218,7 @@ gitcore-tutorial                        guide\n>  gitcredentials                          guide\n>  gitcvs-migration                        guide\n>  gitdatamodel                            guide\n> +gitdetachedhead                         guide\n>  gitdiffcore                             guide\n>  giteveryday                             guide\n>  gitfaq                                  guide\n>\n> base-commit: 5a7d1e8045ce66c908f62598e26cbb8df7b39a90\n\n"},{"id":"554410","messageId":"cb482e6d-0c76-4f34-b72c-03b5234d4f37@app.fastmail.com","threadId":"66484","inReplyTo":"pull.2250.git.1791384721919.gitgitgadget@gmail.com","subject":"Re: [PATCH] doc: checkout: rewrite detached HEAD state explanation","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-10-07T19:02:30Z","receivedAt":"2026-10-07T19:02:30Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"> Re: [PATCH] doc: checkout: rewrite detached HEAD state explanation\n\nThis change adds a standalone guide as well. The subject “just” make it\nsound like you are rewriting the text where it is.\n\nOn Wed, Oct 7, 2026, at 16:52, Julia Evans via GitGitGadget wrote:\n> From: Julia Evans <julia@jvns.ca>\n>\n> The current explanation has the following issues:\n>\n> - Says detached HEAD state is useful but doesn't explain why\n> - Takes many paragraphs before explaining what detached HEAD state is\n> - It's common for users to accidentally end up in detached HEAD state,\n>   but it doesn't explain why that might happen\n> - One of the UI improvements in `git switch` is to make it harder\n>   to detach accidentally, but that isn't advertised.\n>   See 7968bef06b (switch: only allow explicit detached HEAD, 2019-03-29)\n> - Too many confusing diagrams\n>\n> Write a new explanation addressing these issues, and put it in a\n> standalone guide so that we can easily reference it from advice\n> (\"see `git help detachedhead`\").\n> The result is a shorter guide that covers more material.\n>\n> The framing that \"Git considers commits that aren't on a branch/other\n> reference to be garbage\" is taken from Steve Klabnik's tutorial\n> https://steveklabnik.github.io/jujutsu-tutorial/branching-merging-and-conflicts/anonymous-branches.html.\n> It's funny and it's consistent with the way Git uses the term\n> \"garbage collection\".\n>\n> Co-authored-by: Marie Claire LeBlanc Flanagan <hello@marieflanagan.com>\n> Signed-off-by: Julia Evans <julia@jvns.ca>\n> ---\n>     doc: checkout: rewrite detached HEAD state explanation\n>\n>     Often when rewriting these explanations I go through a process where I\n>     ask users' feedback on the old explanation. Here I didn't do that\n>     basically because that process takes a long time and I'm working on a\n>     bunch of other time consuming docs projects so I did a quick rewrite\n>     based on my previous experience explaining detached HEAD state to folks.\n>\n>     I thought this could be a nice quick docs win on a topic which many\n>     users find quite confusing. If the changes here are too controversial I\n>     can drop it for now.\n>\n>     Also if folks object to making a separate git help detachedhead guide\n>     I'm happy to drop that too. Personally I'm excited about the idea of\n>     being able to reference the guides in our advice (which is one of our\n>     best tools for getting users info about how to use Git!), but it's not\n>     possible to let users jump to a subsection, so this is sort of a hack\n>     around that.\n>\n> Published-As:\n> https://github.com/gitgitgadget/git/releases/tag/pr-2250%2Fjvns%2Fdetached-head-v1\n> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git\n> pr-2250/jvns/detached-head-v1\n> Pull-Request: https://github.com/gitgitgadget/git/pull/2250\n>\n>  Documentation/detached-head.adoc   |  43 ++++++++++\n>  Documentation/git-checkout.adoc    | 129 +----------------------------\n>  Documentation/gitdetachedhead.adoc |  14 ++++\n\nWhy in one word instead of hyphenating `detached-head`?\n(gitdetached-head(7))\n\n>  advice.c                           |   1 +\n>  command-list.txt                   |   1 +\n\nThis is missing meson/Makefile changes in order to make\ngitdetachedhead(7).\n\n>  5 files changed, 60 insertions(+), 128 deletions(-)\n>  create mode 100644 Documentation/detached-head.adoc\n>  create mode 100644 Documentation/gitdetachedhead.adoc\n>\n> diff --git a/Documentation/detached-head.adoc\n> b/Documentation/detached-head.adoc\n> new file mode 100644\n> index 0000000000..1e00712124\n> --- /dev/null\n> +++ b/Documentation/detached-head.adoc\n> @@ -0,0 +1,43 @@\n> +`HEAD` is where Git stores your current branch. `HEAD` can either be:\n\nI see that this is similar to gitdatamodel(7). Except it adds “, if\nthere is a current branch”:\n\n    HEAD is where Git stores your current branch, if there is a current\n    branch. HEAD can either be: [...]\n\nBut a potential problem with that is:\n\nA: What is HEAD?\nB: It stores the current branch, if there is a current branch.\nA: Oh so it is *empty* if there is no current branch?\nB: No. Then it stores a commit.\n\nThis is of course revealed later here. But I wonder if starting with\ncurrent-branch can set someone up for a double take.\n\nOne could go in the other direction: you are almost always on a\ncommit. For most people the exception will be the unborn branch state\nafter `git init`. That commit is stored in the thing called `HEAD`. And\nif you are on branch it also points to that branch. (It doesn’t point at\ntwo things at the same time but instead at the branch, which is in turn\npoints at the commit for the branch, but conceptually it’s the same\ndifference).\n\n> +\n> +1. A branch, which is your current branch.\n> +2. A commit ID, when you don't have a current branch.\n> +   This is called \"detached HEAD state\".\n> +\n> +It can sometimes be useful for `HEAD` to be a commit ID.\n> +For example, it lets you look at an old version of your code\n> +(with `git checkout COMMIT_ID`).\n\nMaybe go straight to `git switch --detached COMMIT_ID` here.\n\nIt is very useful to describe detached `HEAD` as something that you can\nfall into by accident. It is very much perenially needed. And this\nparagraph explains a legitimate, intentional use.\n\nBut a dedicated guide is also an opportunity to not only acknowledge hey\nthere is a use here but to explain actively why it is\nconvenient. Because one thing is “detached `HEAD`” as a conceptual,\nscary blind alley where my work might get garbage collected. But only\nthinking in terms of branches and tags can lead to a dead end of only\nthinking of Git as:\n\n1. The state of our collective work right now (“main”)\n2. Our important waypoints (tags)\n\nSo before you lead them out of the maw of the garbage incinerator, you\ncan help level up their use of Git by explaining why checking out\ncommits freely is useful with an example of why they would do that.\n\n1. Finding buggy commits manually (this would probably end with a\n   mention of git-bisect(1))\n2. Testing that each commit on a branch (forked from `main`) passes the\n   test suite\n3. Browsing an interesting commit manually instead of pointing `git\n   grep` at the commit (or something)\n4. Just being on `origin/main` instead of having a `main`. I never\n   update “main”. So why would I go to the trouble of keeping it up to\n   date? I can just “be on” `origin/main` (detached on whatever that\n   points to).\n\n   See also StackOverflow questions about how to update hundreds of\n   local branches with git-pull(1) or something. Why? They do not have\n   hundreds of local branches that they are authoring. They just want\n   those branches by other people to be updated. But that is not\n   necessary for anything. You just need the remote-tracking\n   branches. Including if you want to check them out (on detached\n   `HEAD`).\n\nThis conceptual dead end (of no “detached `HEAD`) could manifest itself\nlike this:\n\n• “I must always be on a branch”\n• “Therefore I can only check out old commits by first creating a\n  branch”\n• “Every interesting commit must have a tag for posteriety so we can\n  name it” (you just need the hash, even abbreviated)\n• “We must tag this commit for the build so we can name the build” (you\n  can just use the hash or use part-of-the-hash with git-describe(1))\n\n> +\n> +The only problem is that if you create new commits while in detached\n> +HEAD state, those commits won't be on a branch. This makes those new\n> +commits much harder to find later. Also, Git considers commits that\n> +aren't on any branch (or a tag or other reference) to be garbage.\n> +Git will eventually permanently delete those \"garbage\" commits during\n> +garbage collection.\n\nMaybe this is where you should mention git-reflog(1) (and git-log(1)\nmaybe (see later)).\n\nMaybe this about garbage collection could be tempered with a mention of\nthe however-many default days for reflog expiry. It’s such a long time\nthat if any of my commits get garbage collected... I probably didn’t\nneed them.\n\n> +\n> +There are 3 main ways you can end up in detached HEAD state\n> +unintentionally:\n\nI would say “typical” instead of “main”. As in these things are the\ntypical gateways to this state (unintentionally).\n\n> +\n> +1. `git checkout COMMIT_ID`, where `COMMIT_ID` is a commit ID\n> +2. `git checkout v1.3`, where v1.3 is a tag name\n> +3. `git checkout origin/main`, where `origin/main` is\n> +   a remote-tracking branch\n> +\n> +Checking out a tag puts you in detached HEAD state because `HEAD` can\n> +only be a branch or a commit, not a tag or any other reference.\n> +So `git checkout TAG` will set HEAD to the commit for that tag.\n\nNice.\n\n> +\n> +The easiest way to avoid accidentally ending up in detached HEAD state\n> +is to use linkgit:git-switch[1] instead of linkgit:git-checkout[1] to\n> +switch branches. `git switch` won't let you detach unless you\n> explicitly\n> +pass the `--detach` argument.\n> +\n> +To get back onto a branch, you can:\n> +\n> +1. Switch to the branch you want to be on, with `git switch BRANCHNAME`.\n> +2. Create a new branch at the current commit, with `git switch -c BRANCHNAME`.\n> +   You might want to do this if you've created new commits, so that you can\n> +   find the commit later and so that it won't be garbage collected.\n> +\n> +If you create commits in detached HEAD state that aren't on a branch,\n> +you can find them later using linkgit:git-reflog[1].\n\nOkay, but it’s more immediate and obvious to use `git log`. Say you\ncreated three commits by accident while not on a branch. Then they will\nbe immediately um logged.\n\ngit-reflog(1) is excellent too of course, mostly because you are likely\nto find all of them if you did a lot of weird checkouts in one session.\n\n> diff --git a/Documentation/git-checkout.adoc\n> b/Documentation/git-checkout.adoc\n> index 2aefea0228..4e9e94e24d 100644\n> --- a/Documentation/git-checkout.adoc\n> +++ b/Documentation/git-checkout.adoc\n> @@ -376,135 +376,8 @@ For more details, see the 'pathspec' entry in\n> [snip]\n\nI didn’t read the rest here.\n\n"}]}