From: "Julia Evans" <julia@jvns.ca>
To: "Junio C Hamano" <gitster@pobox.com>,
"Julia Evans" <gitgitgadget@gmail.com>
Cc: git@vger.kernel.org
Subject: Re: [PATCH] doc: checkout: rewrite detached HEAD state explanation
Date: Tue, 13 Oct 2026 08:54:56 -0400 [thread overview]
Message-ID: <31f8c254-328b-405f-bc26-b077fa57b5ef@app.fastmail.com> (raw)
In-Reply-To: <xmqqik3da2bs.fsf@gitster.g>
Thanks for the review. I'm going to mark comments that I feel are about style issues
(like "could this be explained in a more clear way?") as just "style comment" to deal with
later.
In general if we really want to make sure that this is as clear as possible, I
think it would be most effective to do a second revision later (after merging
this) where we get feedback from users and find out what folks are confused by.
On Wed, Oct 7, 2026, at 12:43 PM, Junio C Hamano wrote:
> "Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
>> diff --git a/Documentation/detached-head.adoc b/Documentation/detached-head.adoc
>> new file mode 100644
>> index 0000000000..1e00712124
>> --- /dev/null
>> +++ b/Documentation/detached-head.adoc
>> @@ -0,0 +1,43 @@
>> +`HEAD` is where Git stores your current branch. `HEAD` can either be:
>> +
>> +1. A branch, which is your current branch.
>> +2. A commit ID, when you don't have a current branch.
>> + This is called "detached HEAD state".
>
> HEAD is branch which can either be a branch or something else?
Style comment. Probably this is the one I'd prioritize the highest.
> HEAD records the state from which your current changes started.
> This can be a branch (the "current branch"), or it may not be
> associated with any concrete branch (in which case HEAD is
> "detached")
>> +It can sometimes be useful for `HEAD` to be a commit ID.
>> +For example, it lets you look at an old version of your code
>> +(with `git checkout COMMIT_ID`).
>
> To "look at" an older state is more versatile than simply running
> 'git show COMMIT_ID:path', as it allows you to do anything you can
> do on a branch, such as building and testing. Thus,
>
> A detached HEAD is useful when you want to tentatively visit
> an old state with 'git checkout --detach v0.1', without
> having to create a dedicated branch for it.
Style comment.
>> +The only problem is that if you create new commits while in detached
>> +HEAD state, those commits won't be on a branch.
>
> I would suggest rephrasing "The only problem" to "One caveat is" or
> something. When sightseeing and experimenting, the ability to
> create throw-away commits without the need to clean them up later,
> or to invent a unique name for a temporary branch, is not a problem.
> It is an advantage.
Style comment.
>> This makes those new
>> +commits much harder to find later. Also, Git considers commits that
>> +aren't on any branch (or a tag or other reference) to be garbage.
>> +Git will eventually permanently delete those "garbage" commits during
>> +garbage collection.
>
> Correct.
>
> Perhaps it is better to clarify this by adding "after you leave
> the detached HEAD state" after "to find later". While you are in
> the detached HEAD state, you can run 'git log' to find the commits
> you created there, as you can do everything you normally can on a
> branch, or use 'git reflog @{now}' for that matter.
>
>> +There are 3 main ways you can end up in detached HEAD state
>> +unintentionally:
>> +
>> +1. `git checkout COMMIT_ID`, where `COMMIT_ID` is a commit ID
>> +2. `git checkout v1.3`, where v1.3 is a tag name
>
> These I wouldn't call "unintentionally". They are documented and
> supported ways to do so, and will remain to be so. "unknowingly"
> may be a more fair way to call these gotchas, though.
Thanks, removed "unintentionally".
>
>> +The easiest way to avoid accidentally ending up in detached HEAD state
>> +is to use linkgit:git-switch[1] instead of linkgit:git-checkout[1] to
>> +switch branches. `git switch` won't let you detach unless you explicitly
>> +pass the `--detach` argument.
>
> Correct, but the motivation to 'avoid accidentally ending up' may
> want to be spelled out. Most often checking out a tag is to go
> sightseeing, where you do not want to 'avoid' detached HEAD.
Style comment.
>> +To get back onto a branch, you can:
>> +
>> +1. Switch to the branch you want to be on, with `git switch BRANCHNAME`.
>> +2. Create a new branch at the current commit, with `git switch -c BRANCHNAME`.
>> + You might want to do this if you've created new commits, so that you can
>> + find the commit later and so that it won't be garbage collected.
>
> Very good.
>
>> +If you create commits in detached HEAD state that aren't on a branch,
>> +you can find them later using linkgit:git-reflog[1].
>
> This, as you already said, is "much harder to find later" option.
> There should be a better recovery option described here before
> resorting to "git reflog HEAD" after you switched back. E.g.,
>
> If you have created commits in detached HEAD state and then
> switched away from the state, all is not lost. "git checkout"
> would have give you a warning message, like this:
>
> Warning: you are leaving 2 commits behind, not connected to
> any of your branches
>
> c816689 typofix the previous
> 8e1bff5 decsribe detached HEAD state better
>
> You can create branches to keep them, e.g., "git branch saved c816689",
> by using the commit object names left there.
Thanks, added a mention of this warning. It's a really nice example of the ways
Git helps avoid issues.
>> diff --git a/Documentation/git-checkout.adoc b/Documentation/git-checkout.adoc
>> index 2aefea0228..4e9e94e24d 100644
>> --- a/Documentation/git-checkout.adoc
>> +++ b/Documentation/git-checkout.adoc
>> @@ -376,135 +376,8 @@ For more details, see the 'pathspec' entry in linkgit:gitglossary[7].
>> [[DETACHED_HEAD]]
>> DETACHED HEAD
>> -------------
>> +include::detached-head.adoc[]
>
> Losing the diagrams is a bit concerning. However, if the intention
> is to have readers learn how HEAD refers to a branch pointing at a
> commit with history structured as a DAG elsewhere in a more basic
> concepts guide, I suspect that it would actually work better. This
> could even be reduced to a simple "see also" pointer to that other
> guide.
>
> If an existing user only uses 'switch' and never reads 'git help
> checkout', they are already not seeing these diagrams, or perhaps
> they learned the concepts elsewhere. They still manage to
> understand Git well enough to make use of it, so perhaps this
> approach is OK. I dunno.
Thanks, good idea to give people a pointer to more info about HEAD.
I'll try adding a pointer to `git help datamodel`.
I'm not against adding diagrams, but I think if we want to add diagrams that
should be a separate project where we actually get feedback from users.
Similarly for explaining `HEAD` in more detail.
next prev parent reply other threads:[~2026-10-13 12:55 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-07 14:52 [PATCH] doc: checkout: rewrite detached HEAD state explanation Julia Evans via GitGitGadget
2026-10-07 16:43 ` Junio C Hamano
2026-10-13 12:54 ` Julia Evans [this message]
2026-10-07 19:02 ` Kristoffer Haugsbakk
2026-10-13 11:48 ` Julia Evans
2026-10-13 12:20 ` Kristoffer Haugsbakk
2026-10-13 12:27 ` Julia Evans
2026-10-13 12:42 ` Julia Evans
2026-10-13 13:01 ` [PATCH v2] " Julia Evans via GitGitGadget
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=31f8c254-328b-405f-bc26-b077fa57b5ef@app.fastmail.com \
--to=julia@jvns.ca \
--cc=git@vger.kernel.org \
--cc=gitgitgadget@gmail.com \
--cc=gitster@pobox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox