Skip to content

Conversation

jvns
Copy link

@jvns jvns commented Aug 25, 2025

  • Remove the numbered list from the beginning
  • Split up the git checkout [<tree-ish>] <pathspec> section into two sections, one for git checkout <tree-ish> <pathspec> and one for git checkout <pathspec>, to match the SYNOPSIS and because it seems like a clearer approach. Also completely rewrite them to be more accurate and more clear. Use "Replace" instead of "Restore".
  • Describe what it means to "switch branches" in a way that's more accessible to newcomers, and make "If the local changes conflict with the changes on ..." more accurate
  • Improve the ARGUMENT DISAMBIGUATION section

cc: "D. Ben Knoble" [email protected]

@jvns jvns force-pushed the clarify-checkout branch 3 times, most recently from 3dc5951 to b641874 Compare August 25, 2025 19:07
@jvns
Copy link
Author

jvns commented Aug 25, 2025

/submit

Copy link

gitgitgadget bot commented Aug 25, 2025

Submitted as [email protected]

To fetch this version into FETCH_HEAD:

git fetch https://github.com/gitgitgadget/git/ pr-1962/jvns/clarify-checkout-v1

To fetch this version to local tag pr-1962/jvns/clarify-checkout-v1:

git fetch --no-tags https://github.com/gitgitgadget/git/ tag pr-1962/jvns/clarify-checkout-v1

Copy link

gitgitgadget bot commented Aug 25, 2025

Error: b641874 was already submitted

@@ -20,10 +20,14 @@ git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>...]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Junio C Hamano wrote (reply to this):

"Julia Evans via GitGitGadget" <[email protected]> writes:

> From: Julia Evans <[email protected]>
>
> - Many users do not understand the terms "index" or "pathspec". Clarify
>   in the intro by using an example, so that users can understand the
>   basic idea without learning the full definition of "pathspec".
> - Use the terminology "Switch" and "Restore" to mirror `git switch`
>   and `git restore`
> - Reference (and clarify) the ARGUMENT DISAMBIGUATION section

Avoid bullet points here.  End your sentence with a full stop.

> -Updates files in the working tree to match the version in the index
> -or the specified tree.  If no pathspec was given, `git checkout` will
> -also update `HEAD` to set the specified branch as the current
> -branch.
> +`git checkout` has two main modes:
> +
> +1. **Switch branches**, with `git checkout <branch>`
> +2. **Restore a different version of a file**, for example with `git
> +   checkout <commit> <filename>` or `git checkout <filename>`
> +
> +See ARGUMENT DISAMBIGUATION below for how Git decides which one to do.

As promised in the proposed log message, this conveys the same
information much more clearly.

"A different version of" neatly sidesteps the need to hint we can
check out paths from a tree or the index.  "Restore a different
version of files" (or "files from a different version") perhaps?
The point being you can grab multiple with a single operation, but
they all have to come from a single source.

Other than that, very nicely done.

> +Here's a description of all of the modes:

I am not sure if we want/need this line, though.

>  `git checkout [<branch>]`::
>  	To prepare for working on _<branch>_, switch to it by updating
> @@ -511,14 +515,17 @@ $ git log -g -2 HEAD
>  ARGUMENT DISAMBIGUATION
>  -----------------------
>  
> -When there is only one argument given and it is not `--` (e.g. `git
> -checkout abc`), and when the argument is both a valid _<tree-ish>_
> -(e.g. a branch `abc` exists) and a valid _<pathspec>_ (e.g. a file
> -or a directory whose name is "abc" exists), Git would usually ask
> -you to disambiguate.  Because checking out a branch is so common an
> -operation, however, `git checkout abc` takes "abc" as a _<tree-ish>_
> -in such a situation.  Use `git checkout -- <pathspec>` if you want
> -to checkout these paths out of the index.
> +When you run `git checkout <something>`, Git tries to guess whether
> +`<something>` is intended to be a branch, a commit, or a set of file(s),
> +and then switches branches, switches commits, or restores the files.
> +
> +If there's a conflict, you can use the double dash `--` to distinguish
> +between branches and files:

I do not think you are dealing with a conflict here, rather
ambiguity.  "You can use double-dash `--` to disambiguate between
branches and paths".


> +* `git checkout <branch> --` will force Git to treat the parameter as a
> +  branch name or commit
> +* `git checkout -- <pathspec>` will force Git to treat the parameter as
> +  a set of file(s)

We do not have to teach the full pathspec syntax here, but I wonder
if we should do something to avoid leading a new reader into
thinking they have to list files.  "...as a set of files and/or
directories", perhaps?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Junio C Hamano wrote (reply to this):

Junio C Hamano <[email protected]> writes:

>> -Updates files in the working tree to match the version in the index
>> -or the specified tree.  If no pathspec was given, `git checkout` will
>> -also update `HEAD` to set the specified branch as the current
>> -branch.
>> +`git checkout` has two main modes:

Another thing I noticed but forgot to mention.

>> +
>> +1. **Switch branches**, with `git checkout <branch>`

Does everybody really understand what it means to "switch branches"
without further explanation?

Also "<branch>" -> "(<branch> | <commit>)", perhaps, as working on
the unnamed branch (aka detached HEAD) behaves very much the same
way as working on a named branch.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, "Julia Evans" wrote (reply to this):

Thanks for the comments!

> Avoid bullet points here.  End your sentence with a full stop.

Ok, will change.

> "Restore a different
> version of files" (or "files from a different version") perhaps?
> The point being you can grab multiple with a single operation, but
> they all have to come from a single source.

I like that, will change.

>> +Here's a description of all of the modes:
>
> I am not sure if we want/need this line, though.

Will remove.

> I do not think you are dealing with a conflict here, rather
> ambiguity.  "You can use double-dash `--` to disambiguate between
> branches and paths".

Will change.

>> +* `git checkout <branch> --` will force Git to treat the parameter as a
>> +  branch name or commit
>> +* `git checkout -- <pathspec>` will force Git to treat the parameter as
>> +  a set of file(s)
>
> We do not have to teach the full pathspec syntax here, but I wonder
> if we should do something to avoid leading a new reader into
> thinking they have to list files.  "...as a set of files and/or
> directories", perhaps?

I like that, will change.

>>> +1. **Switch branches**, with `git checkout <branch>`
>
> Does everybody really understand what it means to "switch branches"
> without further explanation?

My thought was that we explain what "switch branches" in
immediately afterwards in more depth. ("git checkout [<branch>]:
Switch to <branch>. This will update the files in the working tree...)

> Also "<branch>" -> "(<branch> | <commit>)", perhaps, as working on
> the unnamed branch (aka detached HEAD) behaves very much the same
> way as working on a named branch.

I feel mixed about this one.

One way to look at it is that `git checkout` has two modes: one
where you update `HEAD` and one where you don't. I think
from a "git internals" point of view this makes a lot of sense, but
my impression is that most "regular" Git users think of "switching
to detached HEAD state" as being a very different operation from
"switching branches", not as basically equivalent except for one
small detail.

Another way to look at it is that the "git checkout <branch> | <commit>"'s
main role is to switch branches, and that "git checkout <commit>" is
sort of an edge case and that we can leave its explanation to a few
lines later on. That's the stance I've taken here, but I'm open to hearing
other points of view.

checkout <commit> <filename>` or `git checkout <filename>`

See ARGUMENT DISAMBIGUATION below for how Git decides which one to do.
Here's a description of all of the modes:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Junio C Hamano wrote (reply to this):

"Julia Evans via GitGitGadget" <[email protected]> writes:

> From: Julia Evans <[email protected]>
>
> - "To prepare for working on _<branch>_..." is confusing to some users:
>   it makes it sound like these are steps that the user has to do, not
>   steps that Git itself will do. Reword it.
> - Use "changes" instead of "modifications" (which Git normally does)
> - Mention that `git checkout` will fail if there's a merge conflict
> - The current explanation of `You could omit <branch>`... is confusing
>   to users (what are the "expensive side effects"? what's a better way
>   of getting the same info?). Be more direct and mention that `git
>   status` is likely a better option.
>
> Signed-off-by: Julia Evans <[email protected]>
> ---
>  Documentation/git-checkout.adoc | 18 +++++++++---------
>  1 file changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/git-checkout.adoc b/Documentation/git-checkout.adoc
> index ddda891c0ff7..a3edb95973a2 100644
> --- a/Documentation/git-checkout.adoc
> +++ b/Documentation/git-checkout.adoc
> @@ -30,11 +30,12 @@ See ARGUMENT DISAMBIGUATION below for how Git decides which one to do.
>  Here's a description of all of the modes:
>  
>  `git checkout [<branch>]`::
> -	To prepare for working on _<branch>_, switch to it by updating
> -	the index and the files in the working tree, and by pointing
> -	`HEAD` at the branch. Local modifications to the files in the
> -	working tree are kept, so that they can be committed to the
> -	_<branch>_.
> +	Switch to _<branch>_. This will update the files in the working tree,
> +	point `HEAD` at the branch, and update the index. Local changes to
> +	the files in the working tree are kept, so that they can be committed
> +	to the _<branch>_. If the local changes conflict with the changes on
> +	_<branch>_, no changes will be made and the checkout operation will
> +	fail.

Do we expect readers to truly understand what is to "switch to branch"
without explanation?  IOW, I am undecided if the lost "To prepare for
working on" is a good thing.

Usually with "changes on _<branch>_", people mean quite a different
thing from what the above paragraph refers to.

Imagine that you are on a branch that you forked from 'main' some
time ago, built a handful of commits, among which there may be ones
that touch file F.  You further have local modification to file F.
Now you want to switch to another branch.  That branch, since it
forked from 'main', never touched F.  Your local changes do not
conflict with "the changes on branch" (there is no changes on branch
to conflict with your work, as F stayed the same).

To improve, "with the changes on _<branch>_" should be phrased more like
"with the differences between the current state and that of the
_<branch>_" or something.

>  +
>  If _<branch>_ is not found but there does exist a tracking branch in
>  exactly one remote (call it _<remote>_) with a matching name and
> @@ -44,10 +45,9 @@ exactly one remote (call it _<remote>_) with a matching name and
>  $ git checkout -b <branch> --track <remote>/<branch>
>  ------------
>  +
> -You could omit _<branch>_, in which case the command degenerates to
> -"check out the current branch", which is a glorified no-op with
> -rather expensive side-effects to show only the tracking information,
> -if it exists, for the current branch.
> +Running `git checkout` without specifying a branch will output the
> +tracking information, if it exists, for the current branch, but it's
> +slower than getting the same information from `git status`.

I do not think "glorified no-op" is a reference to "status".  At least,
when I wrote it, I didn't mean it that way to compare this glorified
no-op with "git status" [*].  It is a reference to "even though you are
invoking the 'checkout' command, you are not checking out anything."
The side effect is to see the tracking information, which is "rather
expensive side-effects"---compared to doing nothing, anything is
expensive ;-).

I strongly suspect that running "git status" is much more costly than
"git checkout", simply because the former has to do a lot more than just
peeking the tracking information; it internally runs diff between HEAD
and the index, and between the index and the working tree, and it also
has to find and list untracked paths.  Both commands compute the
tracking info by calling the same remote.c::format_tracking_info()
function.

Other than these minor points, the new text seems a definite
improvement.


[References]

 * https://lore.kernel.org/git/[email protected]/
   is where the "glorified no-op" came from.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, "Julia Evans" wrote (reply to this):

> Do we expect readers to truly understand what is to "switch to branch"
> without explanation?  IOW, I am undecided if the lost "To prepare for
> working on" is a good thing.

I'm not sure what you mean here: "switch to <branch>" is as far as I can tell
the most widely used term to refer to this operation, in other Git
resources, in Git's own man pages, and in the error output of the 
`git checkout` command itself:
("Please commit your changes or stash them before you switch branches.")
Which readers do you think would be confused by it?

> Usually with "changes on _<branch>_", people mean quite a different
> thing from what the above paragraph refers to.
>
> Imagine that you are on a branch that you forked from 'main' some
> time ago, built a handful of commits, among which there may be ones
> that touch file F.  You further have local modification to file F.
> Now you want to switch to another branch.  That branch, since it
> forked from 'main', never touched F.  Your local changes do not
> conflict with "the changes on branch" (there is no changes on branch
> to conflict with your work, as F stayed the same).
>
> To improve, "with the changes on _<branch>_" should be phrased more like
> "with the differences between the current state and that of the
> _<branch>_" or something.

That makes sense. I'll work on a better way to phrase this.

> I do not think "glorified no-op" is a reference to "status".  At least,
> when I wrote it, I didn't mean it that way to compare this glorified
> no-op with "git status" [*].  It is a reference to "even though you are
> invoking the 'checkout' command, you are not checking out anything."
> The side effect is to see the tracking information, which is "rather
> expensive side-effects"---compared to doing nothing, anything is
> expensive ;-).
>
> I strongly suspect that running "git status" is much more costly than
> "git checkout", simply because the former has to do a lot more than just
> peeking the tracking information; it internally runs diff between HEAD
> and the index, and between the index and the working tree, and it also
> has to find and list untracked paths.  Both commands compute the
> tracking info by calling the same remote.c::format_tracking_info()
> function.

Ah, I thought `git status` was faster because I benchmarked it it on one
of my repositories and got these results [1]. 

Now that I see that that's not what "expensive side-effects" was intended
to mean, will change to something much simpler, like "Running `git checkout`
without specifying a branch outputs the tracking information for the current
branch. It has no other effect. "

- Julia

[1]
$ hyperfine 'git status'
Benchmark 1: git status
  Time (mean ± σ):       6.6 ms ±   1.2 ms    [User: 3.2 ms, System: 5.1 ms]
$ hyperfine 'git checkout'
  Time (mean ± σ):      29.5 ms ±   1.9 ms    [User: 12.6 ms, System: 14.8 ms]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Junio C Hamano wrote (reply to this):

"Julia Evans" <[email protected]> writes:

>> Do we expect readers to truly understand what is to "switch to branch"
>> without explanation?  IOW, I am undecided if the lost "To prepare for
>> working on" is a good thing.
>
> I'm not sure what you mean here: "switch to <branch>" is as far as I can tell
> the most widely used term to refer to this operation, in other Git
> resources, in Git's own man pages, and in the error output of the 
> `git checkout` command itself:

My assumption was that you are making this a manual to teach what
"switch to branch" means to folks who do not know, hence my
question.

> ("Please commit your changes or stash them before you switch branches.")
> Which readers do you think would be confused by it?

Exactly those who are given that message and want to understand what
it means.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, "Julia Evans" wrote (reply to this):

> My assumption was that you are making this a manual to teach what
> "switch to branch" means to folks who do not know, hence my
> question.

Thanks for bringing this up, I think the question of audience is very important.

My main goal right now is actually to make the Git documentation understandable
for existing Git users who have already been using Git for at least a year or
two. From the feedback I'm getting so far, the man pages are very hard
to understand for those users, and even for many users who have been using Git
for 10+ years.

The reason that I've been thinking of "existing Git users" and not
"newcomers to Git" as the primary audience are:

a) existing users are likely to be the main users of the man pages (after all,
beginners don't _stay_ beginners for very long!)
b) my impression is that the Git documentation always aims to explain everything
in a way that's "completely technically accurate" (which I think makes sense!),
and I I think it's often impossible to give a completely technically accurate
explanation in a way that a newcomer to Git can completely understand.

That said, of course I'm not against making things accessible to newcomers :)
My usual approach in technical writing is to think of "a user who's been using
this software for a couple of years already" as the _primary_ audience, but
also to try to keep it as accessible to a newcomer as possible.

I think I can figure out how to say something about what it means to "Switch
branches" that a newcomer to Git might understand, though of course it'll need
to be quite different than the current explanation (existing users generally
don't understand what "HEAD" or the "index" are, so a newcomer likely won't
understand those terms either).

<branch>` would check out that branch without detaching `HEAD`).
The same as `git checkout <branch>`, except that instead of pointing
`HEAD` at the branch, it points `HEAD` at the commit ID.
See the "DETACHED HEAD" section below for more.
+
Omitting _<branch>_ detaches `HEAD` at the tip of the current branch.

`git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <pathspec>...`::
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Junio C Hamano wrote (reply to this):

"Julia Evans via GitGitGadget" <[email protected]> writes:

> diff --git a/Documentation/git-checkout.adoc b/Documentation/git-checkout.adoc
> index b343d292b30b..9f2b86ac5368 100644
> --- a/Documentation/git-checkout.adoc
> +++ b/Documentation/git-checkout.adoc
> @@ -82,20 +82,21 @@ Omitting _<branch>_ detaches `HEAD` at the tip of the current branch.
>  `git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <pathspec>...`::
>  `git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] --pathspec-from-file=<file> [--pathspec-file-nul]`::
>  
> -	Overwrite the contents of the files that match the pathspec.
> -	When the _<tree-ish>_ (most often a commit) is not given,
> -	overwrite working tree with the contents in the index.
> -	When the _<tree-ish>_ is given, overwrite both the index and
> -	the working tree with the contents at the _<tree-ish>_.
> +	Restore another version of the file(s) that match the pathspec.

The same comment about "files and directories from a different
version" applies here.

Also, I am not so sure about the claim that the verb "restore" is
better understood than "overwrite" due to the presence of "git
restore".  If you are working on, say, an older maintenance track,
and want to borrow what is in a few files from the development
branch, you may say "git restore --source=develop files..." go grab
them down to your current working tree.  But at least to me,
"restore" has a connotation to get back what you used to have, but
the contents in these files you are grabbing had not existed on the
older maintenance track you are working on, ever, and "restore" had
always made me go "Huh?".

I am not suggesting to change the command name "restore"; I am
suggesting the operation that command does using a verb that is
different from "restore" (in an ancient thread, we tried to explain
"checkout" without using "checkout" as the primary verb to describe
what it does, it is the same thing).

>  +
> -The index may contain unmerged entries because of a previous failed merge.
> -By default, if you try to check out such an entry from the index, the
> -checkout operation will fail and nothing will be checked out.
> -Using `-f` will ignore these unmerged entries.  The contents from a

> +If you specify a commit or tree to restore from (for example `git
> +checkout main file.txt`), this will restore the version of the file(s)
> +from that commit or tree. This overwrites the file in the working
> +directory and stages the file's contents.

OK.  I suspect the most common is to "restore" from HEAD, and the
"Huh?"ness of using the verb "restore" goes away.  It clearly is
getting you back to where you were back when your working tree was
in sync with HEAD.  Perhaps use "git checkout HEAD file.txt" for the
example?

> +If you do not specify where to restore from (for example `git checkout
> +file.txt`), this will replace the file(s) with the version from the index.

That is a very negative way to state it.  It is not "do not specify
where".  If you do not give tree, you are actively specifying that
you want things from the index.

> +If you check out a file with an unresolved merge
> +conflict, the checkout operation will fail and no changes will be made.

This is confusing in a way different from the original.  During a
conflicted merge, you will see a few stages until they are resolved.

 (1) The working tree file has conflict markers and text from
     multiple variants.  The index has higher-stage cache entry for
     such a path.

 (2) The user edits the working tree file to resolve the conflicts.
     Once all the conflict markers are removed, some people may say
     "the merge conflict has been resolved".  To Git, the path is
     still unmerged.

 (3) The user tells the index what the resolution is, with commands
     like "git add", "git rm", and the like.  The higher-stage cache
     entries in the index for the path are moved and replaced with a
     single stage-0 entry.  To Git, the path is now merged.

So, "a file with an unresolved merge conflict" would not mean what
you wanted to say for those who consider that dealing with the
working tree files is enough to declare victory and consider the
conflict has been resolved.

> +Using `-f` will ignore the merge conflict.  The contents from a

This changes the meaning to most people from what the original
meant.  If you have a file F with merge conflicts in the earlier
part but the later part merged cleanly, does "git checkout -f F"
ignore the conflicted part and overwrite the rest of the file
somehow?

If you wanted to avoid the term "unmerged cache entries", you can
say "unmerged paths".

Taking all of the above into consideration, perhaps...

    When you are in the middle of a conflicted merge (or
    cherry-pick, "stash pop", etc.) and haven't told Git what the
    resolution for these conflicted paths are with "git add" and
    friends, using "git checkout" to check out such an unmerged path
    out of the index would fail and the command exits with non-zero
    exit status.

    When the `-f` option is given, these unmerged paths are left
    untouched, instead of triggering an error.  For all other
    (i.e. merged) paths that match the <pathspec>, the working tree
    files are overwritten by the version recorded in the index.

or something along that line, but with a readability enhancement
like you have been doing in your series ;-).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, "Julia Evans" wrote (reply to this):

On Tue, Aug 26, 2025, at 6:43 PM, Junio C Hamano wrote:
> "Julia Evans via GitGitGadget" <[email protected]> writes:
>
>> diff --git a/Documentation/git-checkout.adoc b/Documentation/git-checkout.adoc
>> index b343d292b30b..9f2b86ac5368 100644
>> --- a/Documentation/git-checkout.adoc
>> +++ b/Documentation/git-checkout.adoc
>> @@ -82,20 +82,21 @@ Omitting _<branch>_ detaches `HEAD` at the tip of the current branch.
>>  `git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <pathspec>...`::
>>  `git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] --pathspec-from-file=<file> [--pathspec-file-nul]`::
>>  
>> -	Overwrite the contents of the files that match the pathspec.
>> -	When the _<tree-ish>_ (most often a commit) is not given,
>> -	overwrite working tree with the contents in the index.
>> -	When the _<tree-ish>_ is given, overwrite both the index and
>> -	the working tree with the contents at the _<tree-ish>_.
>> +	Restore another version of the file(s) that match the pathspec.
>
> The same comment about "files and directories from a different
> version" applies here.
>
> Also, I am not so sure about the claim that the verb "restore" is
> better understood than "overwrite" due to the presence of "git
> restore".  If you are working on, say, an older maintenance track,
> and want to borrow what is in a few files from the development
> branch, you may say "git restore --source=develop files..." go grab
> them down to your current working tree.  But at least to me,
> "restore" has a connotation to get back what you used to have, but
> the contents in these files you are grabbing had not existed on the
> older maintenance track you are working on, ever, and "restore" had
> always made me go "Huh?".
>
> I am not suggesting to change the command name "restore"; I am
> suggesting the operation that command does using a verb that is
> different from "restore" (in an ancient thread, we tried to explain
> "checkout" without using "checkout" as the primary verb to describe
> what it does, it is the same thing).
>
>>  +
>> -The index may contain unmerged entries because of a previous failed merge.
>> -By default, if you try to check out such an entry from the index, the
>> -checkout operation will fail and nothing will be checked out.
>> -Using `-f` will ignore these unmerged entries.  The contents from a
>
>> +If you specify a commit or tree to restore from (for example `git
>> +checkout main file.txt`), this will restore the version of the file(s)
>> +from that commit or tree. This overwrites the file in the working
>> +directory and stages the file's contents.
>
> OK.  I suspect the most common is to "restore" from HEAD, and the
> "Huh?"ness of using the verb "restore" goes away.  It clearly is
> getting you back to where you were back when your working tree was
> in sync with HEAD.  Perhaps use "git checkout HEAD file.txt" for the
> example?
>
>> +If you do not specify where to restore from (for example `git checkout
>> +file.txt`), this will replace the file(s) with the version from the index.
>
> That is a very negative way to state it.  It is not "do not specify
> where".  If you do not give tree, you are actively specifying that
> you want things from the index.
>
>> +If you check out a file with an unresolved merge
>> +conflict, the checkout operation will fail and no changes will be made.
>
> This is confusing in a way different from the original.  During a
> conflicted merge, you will see a few stages until they are resolved.
>
>  (1) The working tree file has conflict markers and text from
>      multiple variants.  The index has higher-stage cache entry for
>      such a path.
>
>  (2) The user edits the working tree file to resolve the conflicts.
>      Once all the conflict markers are removed, some people may say
>      "the merge conflict has been resolved".  To Git, the path is
>      still unmerged.
>
>  (3) The user tells the index what the resolution is, with commands
>      like "git add", "git rm", and the like.  The higher-stage cache
>      entries in the index for the path are moved and replaced with a
>      single stage-0 entry.  To Git, the path is now merged.
>
> So, "a file with an unresolved merge conflict" would not mean what
> you wanted to say for those who consider that dealing with the
> working tree files is enough to declare victory and consider the
> conflict has been resolved.
>
>> +Using `-f` will ignore the merge conflict.  The contents from a
>
> This changes the meaning to most people from what the original
> meant.  If you have a file F with merge conflicts in the earlier
> part but the later part merged cleanly, does "git checkout -f F"
> ignore the conflicted part and overwrite the rest of the file
> somehow?
>
> If you wanted to avoid the term "unmerged cache entries", you can
> say "unmerged paths".
>
> Taking all of the above into consideration, perhaps...
>
>     When you are in the middle of a conflicted merge (or
>     cherry-pick, "stash pop", etc.) and haven't told Git what the
>     resolution for these conflicted paths are with "git add" and
>     friends, using "git checkout" to check out such an unmerged path
>     out of the index would fail and the command exits with non-zero
>     exit status.
>
>     When the `-f` option is given, these unmerged paths are left
>     untouched, instead of triggering an error.  For all other
>     (i.e. merged) paths that match the <pathspec>, the working tree
>     files are overwritten by the version recorded in the index.
>
> or something along that line, but with a readability enhancement
> like you have been doing in your series ;-).

Thanks, this section of the man page is not easy and this is very
useful feedback. Will work on improving all of these points.

Copy link

gitgitgadget bot commented Aug 27, 2025

This patch series was integrated into seen via git@2d3eb29.

@gitgitgadget gitgitgadget bot added the seen label Aug 27, 2025
Copy link

gitgitgadget bot commented Aug 27, 2025

This branch is now known as je/doc-checkout.

@@ -20,10 +20,14 @@ git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>...]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, "D. Ben Knoble" wrote (reply to this):

On Mon, Aug 25, 2025 at 3:09 PM Julia Evans via GitGitGadget
<[email protected]> wrote:
>
> From: Julia Evans <[email protected]>
>
> - Many users do not understand the terms "index" or "pathspec". Clarify
>   in the intro by using an example, so that users can understand the
>   basic idea without learning the full definition of "pathspec".
> - Use the terminology "Switch" and "Restore" to mirror `git switch`
>   and `git restore`
> - Reference (and clarify) the ARGUMENT DISAMBIGUATION section
>
> Signed-off-by: Julia Evans <[email protected]>
> ---
>  Documentation/git-checkout.adoc | 31 +++++++++++++++++++------------
>  1 file changed, 19 insertions(+), 12 deletions(-)
>
> diff --git a/Documentation/git-checkout.adoc b/Documentation/git-checkout.adoc
> index 40e02cfd6562..ddda891c0ff7 100644
> --- a/Documentation/git-checkout.adoc
> +++ b/Documentation/git-checkout.adoc
> @@ -20,10 +20,14 @@ git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>...]
>
>  DESCRIPTION
>  -----------
> -Updates files in the working tree to match the version in the index
> -or the specified tree.  If no pathspec was given, `git checkout` will
> -also update `HEAD` to set the specified branch as the current
> -branch.
> +`git checkout` has two main modes:
> +
> +1. **Switch branches**, with `git checkout <branch>`
> +2. **Restore a different version of a file**, for example with `git
> +   checkout <commit> <filename>` or `git checkout <filename>`
> +
> +See ARGUMENT DISAMBIGUATION below for how Git decides which one to do.
> +Here's a description of all of the modes:

This looks good—I initially scratched my head thinking there were 3
modes, but unifying "update files to match index" and "update files to
match specified tree" is easier to digest in this presentation.

>
>  `git checkout [<branch>]`::
>         To prepare for working on _<branch>_, switch to it by updating
> @@ -511,14 +515,17 @@ $ git log -g -2 HEAD
>  ARGUMENT DISAMBIGUATION
>  -----------------------
>
> -When there is only one argument given and it is not `--` (e.g. `git
> -checkout abc`), and when the argument is both a valid _<tree-ish>_
> -(e.g. a branch `abc` exists) and a valid _<pathspec>_ (e.g. a file
> -or a directory whose name is "abc" exists), Git would usually ask
> -you to disambiguate.  Because checking out a branch is so common an
> -operation, however, `git checkout abc` takes "abc" as a _<tree-ish>_
> -in such a situation.  Use `git checkout -- <pathspec>` if you want
> -to checkout these paths out of the index.
> +When you run `git checkout <something>`, Git tries to guess whether
> +`<something>` is intended to be a branch, a commit, or a set of file(s),
> +and then switches branches, switches commits, or restores the files.
> +
> +If there's a conflict, you can use the double dash `--` to distinguish
> +between branches and files:
> +
> +* `git checkout <branch> --` will force Git to treat the parameter as a
> +  branch name or commit
> +* `git checkout -- <pathspec>` will force Git to treat the parameter as
> +  a set of file(s)

I think we've dropped the bit about the default interpretation of "git
checkout <something>". Maybe

    When you run `git checkout <something>`, Git tries to guess whether
    `<something>` is intended to be a branch, a commit, or a set of file(s),
    and then switches branches, switches commits, or restores the files.

    By default, Git interprets `<something>` as a _<tree-ish>_.
    [explain what choosing a tree-ish means for the user?]

    [Your notes on disambiguation as before]

?

>
>  EXAMPLES
>  --------
> --
> gitgitgadget
>
>


-- 
D. Ben Knoble

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, "Julia Evans" wrote (reply to this):

> I think we've dropped the bit about the default interpretation of "git
> checkout <something>". Maybe
>
>     When you run `git checkout <something>`, Git tries to guess whether
>     `<something>` is intended to be a branch, a commit, or a set of file(s),
>     and then switches branches, switches commits, or restores the files.
>
>     By default, Git interprets `<something>` as a _<tree-ish>_.
>     [explain what choosing a tree-ish means for the user?]
>
>     [Your notes on disambiguation as before]

Thanks, will fix. Though I don't think it's accurate that
Git will treat <something> as a <tree-ish> in this context, since
`git checkout <tree>` is not valid. Will find a different wording.
(I get "fatal: Cannot switch branch to a non-commit")

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Junio C Hamano wrote (reply to this):

"Julia Evans" <[email protected]> writes:

>> I think we've dropped the bit about the default interpretation of "git
>> checkout <something>". Maybe
>>
>>     When you run `git checkout <something>`, Git tries to guess whether
>>     `<something>` is intended to be a branch, a commit, or a set of file(s),
>>     and then switches branches, switches commits, or restores the files.
>>
>>     By default, Git interprets `<something>` as a _<tree-ish>_.
>>     [explain what choosing a tree-ish means for the user?]
>>
>>     [Your notes on disambiguation as before]
>
> Thanks, will fix. Though I don't think it's accurate that
> Git will treat <something> as a <tree-ish> in this context, since
> `git checkout <tree>` is not valid. Will find a different wording.
> (I get "fatal: Cannot switch branch to a non-commit")

True.  "git checkout foo" is disambiguated by seeing if 'foo' can be
interpreted as a commit-ish, and if not, if there is a path 'foo' in
the working tree.  Otherwise we'd get an ambiguity error.  A commit-ish
that is nameed by giving a branch name and other commit-ish then trigger
a bit different codepaths (the former results in checking out a branch,
the latter detached HEAD).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, "D. Ben Knoble" wrote (reply to this):

On Thu, Aug 28, 2025 at 7:44 PM Junio C Hamano <[email protected]> wrote:
>
> "Julia Evans" <[email protected]> writes:
>
> >> I think we've dropped the bit about the default interpretation of "git
> >> checkout <something>". Maybe
> >>
> >>     When you run `git checkout <something>`, Git tries to guess whether
> >>     `<something>` is intended to be a branch, a commit, or a set of file(s),
> >>     and then switches branches, switches commits, or restores the files.
> >>
> >>     By default, Git interprets `<something>` as a _<tree-ish>_.
> >>     [explain what choosing a tree-ish means for the user?]
> >>
> >>     [Your notes on disambiguation as before]
> >
> > Thanks, will fix. Though I don't think it's accurate that
> > Git will treat <something> as a <tree-ish> in this context, since
> > `git checkout <tree>` is not valid. Will find a different wording.
> > (I get "fatal: Cannot switch branch to a non-commit")

Interesting. A docs bug! :) AFAICT it comes from 19e5656345
(checkout.txt: document a common case that ignores ambiguation rules,
2016-09-07). I was a novice then and don't know the behavior from that
period, nor did I bother to find out whether "tree-ish" matched the
behavior at the time and has changed or was simply wrong from the
start. Good catch.

> True.  "git checkout foo" is disambiguated by seeing if 'foo' can be
> interpreted as a commit-ish, and if not, if there is a path 'foo' in
> the working tree.  Otherwise we'd get an ambiguity error.  A commit-ish
> that is nameed by giving a branch name and other commit-ish then trigger
> a bit different codepaths (the former results in checking out a branch,
> the latter detached HEAD).

Yep, makes sense.

-- 
D. Ben Knoble

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Junio C Hamano wrote (reply to this):

"D. Ben Knoble" <[email protected]> writes:

>> +1. **Switch branches**, with `git checkout <branch>`
>> +2. **Restore a different version of a file**, for example with `git
>> +   checkout <commit> <filename>` or `git checkout <filename>`
>> +
>> +See ARGUMENT DISAMBIGUATION below for how Git decides which one to do.
>> +Here's a description of all of the modes:
>
> This looks good—I initially scratched my head thinking there were 3
> modes, but unifying "update files to match index" and "update files to
> match specified tree" is easier to digest in this presentation.

Yup.  And on the other side, unifying "prepare to extend the history
of a branch" and "prepare to create a new history starting at a
commit" (aka detached HEAD) into one is equally good.

But I am wondering what is the most common perception of the second
mode.  I've always thought that the action was to "grab things out
of the index or out of a tree-ish and overwrite the working tree
files", and it takes me an extra effort to read, think, understand
and finally realize that "update working tree files to match either
the index or a tree-ish" is equivalent to it.

Anyway, thanks for a review.

Copy link

gitgitgadget bot commented Aug 28, 2025

User "D. Ben Knoble" <[email protected]> has been added to the cc: list.

<branch>` would check out that branch without detaching `HEAD`).
The same as `git checkout <branch>`, except that instead of pointing
`HEAD` at the branch, it points `HEAD` at the commit ID.
See the "DETACHED HEAD" section below for more.
+
Omitting _<branch>_ detaches `HEAD` at the tip of the current branch.

`git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <pathspec>...`::
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, "D. Ben Knoble" wrote (reply to this):

On Mon, Aug 25, 2025 at 3:31 PM Julia Evans via GitGitGadget
<[email protected]> wrote:
>
> From: Julia Evans <[email protected]>
>
> - Use the term "Restore" to mirror `git restore`
> - Many Git users do not know what a "tree-ish" is. Clarify by using an
>   example of each case, and by saying "commit or tree" in the text
>   instead of "<tree-ish>"

Wishful thinking (see glossary comments): I wish we could teach them
about "tree-ish"s here rather than stop using useful shorthands
altogether. Of course, then we have to wonder where we can use the
shorthand and where we must do the "spell it out (give an
abbreviation)" dance. Hm.

> diff --git a/Documentation/git-checkout.adoc b/Documentation/git-checkout.adoc
> index b343d292b30b..9f2b86ac5368 100644
> --- a/Documentation/git-checkout.adoc
> +++ b/Documentation/git-checkout.adoc
> @@ -82,20 +82,21 @@ Omitting _<branch>_ detaches `HEAD` at the tip of the current branch.
> -The index may contain unmerged entries because of a previous failed merge.
> -By default, if you try to check out such an entry from the index, the
> -checkout operation will fail and nothing will be checked out.
> -Using `-f` will ignore these unmerged entries.  The contents from a
> +If you specify a commit or tree to restore from (for example `git
> +checkout main file.txt`), this will restore the version of the file(s)
> +from that commit or tree. This overwrites the file in the working
> +directory and stages the file's contents.
> ++
> +If you do not specify where to restore from (for example `git checkout
> +file.txt`), this will replace the file(s) with the version from the index.
> +If you check out a file with an unresolved merge

Possibly a missing paragraph break here?

> +conflict, the checkout operation will fail and no changes will be made.
> +Using `-f` will ignore the merge conflict.  The contents from a
>  specific side of the merge can be checked out of the index by
>  using `--ours` or `--theirs`.  With `-m`, changes made to the working tree
>  file can be discarded to re-create the original conflicted merge result.
> -
>  `git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>...]`::

I think I would expect to keep this break, but I might be misreading something.

-- 
D. Ben Knoble

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, "Julia Evans" wrote (reply to this):

> Wishful thinking (see glossary comments): I wish we could teach them
> about "tree-ish"s here rather than stop using useful shorthands
> altogether. Of course, then we have to wonder where we can use the
> shorthand and where we must do the "spell it out (give an
> abbreviation)" dance. Hm.

What I find hard about documenting cases like this is identifying
the use case for providing so much flexibility
("you can pass any tree, not just a commit!), since personally
I've never passed anything to `git checkout` other than a commit.

I've been trying to think of examples of cases where it's useful
to pass a tree instead of a commit. I can see that it's possible to run
something like this

$ git checkout HEAD:Documentation/ git-commit.adoc

to restore `file.txt` into a different directory than it was originally.
This seems cool in theory but it's hard for me to see why it's useful,
which makes it hard for me to document. What I would tell a friend is
"<tree-ish> 99% of the time just means "commit or something
which resolves to a commit, but Git has made it more general for
a reason I don't understand", but of course that's not the right
thing to say in the Git documentation :)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Junio C Hamano wrote (reply to this):

"Julia Evans" <[email protected]> writes:

> $ git checkout HEAD:Documentation/ git-commit.adoc
>
> to restore `file.txt` into a different directory than it was originally.

It probably is handy when you want to cross a rename boundary to
backport a new thing into an old history (or vice versa).  Something
like

    $ git checkout v1.0.0
    $ git checkout v1.7.1:builtin cat-file.c

perhaps.

> What I would tell a friend is
> "<tree-ish> 99% of the time just means "commit or something
> which resolves to a commit, but Git has made it more general for
> a reason I don't understand", but of course that's not the right
> thing to say in the Git documentation :)

You are describing commit-ish (which allows an annotated or signed
tag that points at a commit).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, "D. Ben Knoble" wrote (reply to this):

On Thu, Aug 28, 2025 at 4:00 PM Julia Evans <[email protected]> wrote:
>
> > Wishful thinking (see glossary comments): I wish we could teach them
> > about "tree-ish"s here rather than stop using useful shorthands
> > altogether. Of course, then we have to wonder where we can use the
> > shorthand and where we must do the "spell it out (give an
> > abbreviation)" dance. Hm.
>
> What I find hard about documenting cases like this is identifying
> the use case for providing so much flexibility
> ("you can pass any tree, not just a commit!), since personally
> I've never passed anything to `git checkout` other than a commit.

This makes sense, and: I think some of how I learned more Git was to
read the manuals, look up things I wasn't familiar with, and then play
with them :) So in a sense my wishful thinking is about sign-posting
"here's this other nook to explore if you're curious" (knowing that
~70% or or more simply won't be).

> I've been trying to think of examples of cases where it's useful
> to pass a tree instead of a commit. I can see that it's possible to run
> something like this
>
> $ git checkout HEAD:Documentation/ git-commit.adoc
>
> to restore `file.txt` into a different directory than it was originally.
> This seems cool in theory but it's hard for me to see why it's useful,
> which makes it hard for me to document. What I would tell a friend is
> "<tree-ish> 99% of the time just means "commit or something
> which resolves to a commit, but Git has made it more general for
> a reason I don't understand", but of course that's not the right
> thing to say in the Git documentation :)

I would say that it's more general in part because it can be: the data
model allows it without any extra effort (not a jab at the
programming, which was probably not easy!). But I'm in a tangent now
and the latest version is probably fine by me. I just don't want to
lose the signposts for explorers.

-- 
D. Ben Knoble

Copy link

gitgitgadget bot commented Aug 28, 2025

This patch series was integrated into seen via git@a25a411.

jvns added 5 commits August 28, 2025 18:54
- Many users do not understand the terms "index" or "pathspec". Clarify
  in the intro by using an example, so that users can understand the
  basic idea without learning the full definition of "pathspec".
- Use the terminology "Switch" and "Restore" to mirror `git switch`
  and `git restore`
- Reference (and clarify) the ARGUMENT DISAMBIGUATION section

Signed-off-by: Julia Evans <[email protected]>
- "To prepare for working on _<branch>_..." is confusing to some users:
  it makes it sound like these are steps that the user has to do, not
  steps that Git itself will do. Reword it.
- Use "changes" instead of "modifications" (which Git normally does)
- Mention that `git checkout` will fail if there's a merge conflict
- The current explanation of `You could omit <branch>`... is confusing
  to users (what are the "expensive side effects"? what's a better way
  of getting the same info?). Be more direct and mention that `git
  status` is likely a better option.

Signed-off-by: Julia Evans <[email protected]>
Many Git users don't know what the term "reset" means. Resolve this by:

- Expanding it into its definition, in one case
- Giving a simpler but still accurate explanation ("the branch will not
  be created or modified"), in the other case

Signed-off-by: Julia Evans <[email protected]>
Right now the explanation of `--detach` repeats a lot of the content in
the description of `git checkout <branch>`: we can communicate the same
thing by saying "This is the same as `git checkout <branch>`, except..."

Signed-off-by: Julia Evans <[email protected]>
- Split up the forms `git checkout file.txt` and
  `git checkout main file.txt` to match what's given in the SYNOPSIS
- Remove `-f` from the SYNOPSIS for the second form, since according to
  this man page it is not relevant in that context
- Many Git users do not know what a "tree-ish" is. Clarify by using an
  example of each case, and by saying "commit or tree" in the text
  instead of "<tree-ish>"
- Many Git users do not know what the "index" is. Instead say "stage the
  file's contents" where appropriate, since Git often uses "stage" as a
  verb to mean the same thing as "add to the index" and it's a more
  familiar term.
- Use "Discard unstaged changes" instead of "checking out paths from
  the index" where relevant

Signed-off-by: Julia Evans <[email protected]>
@jvns jvns force-pushed the clarify-checkout branch from b641874 to 9c0119e Compare August 28, 2025 22:55
Copy link

gitgitgadget bot commented Aug 29, 2025

This patch series was integrated into seen via git@3416196.

@jvns
Copy link
Author

jvns commented Aug 29, 2025

/submit

Copy link

gitgitgadget bot commented Aug 29, 2025

Submitted as [email protected]

To fetch this version into FETCH_HEAD:

git fetch https://github.com/gitgitgadget/git/ pr-1962/jvns/clarify-checkout-v2

To fetch this version to local tag pr-1962/jvns/clarify-checkout-v2:

git fetch --no-tags https://github.com/gitgitgadget/git/ tag pr-1962/jvns/clarify-checkout-v2

@@ -20,10 +20,12 @@ git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>...]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Junio C Hamano wrote (reply to this):

"Julia Evans via GitGitGadget" <[email protected]> writes:

> From: Julia Evans <[email protected]>
>
> - Many users do not understand the terms "index" or "pathspec". Clarify
>   in the intro by using an example, so that users can understand the
>   basic idea without learning the full definition of "pathspec".
> - Use the terminology "Switch" and "Restore" to mirror `git switch`
>   and `git restore`
> - Reference (and clarify) the ARGUMENT DISAMBIGUATION section
>
> Signed-off-by: Julia Evans <[email protected]>
> ---

You seem to have forgotten to update the proposed log message ...

https://lore.kernel.org/git/[email protected]/

... to avoid making it just an enumeration of "these random things
were done in this patch" (and instead tell a coherent story).

The same comment applies to many of your patches in this and other
topics (I won't repeat for brevity, though, on my review on them).

>  Documentation/git-checkout.adoc | 29 +++++++++++++++++------------
>  1 file changed, 17 insertions(+), 12 deletions(-)
>
> diff --git a/Documentation/git-checkout.adoc b/Documentation/git-checkout.adoc
> index 40e02cfd65..c86941ad53 100644
> --- a/Documentation/git-checkout.adoc
> +++ b/Documentation/git-checkout.adoc
> @@ -20,10 +20,12 @@ git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>...]
>  
>  DESCRIPTION
>  -----------
> -Updates files in the working tree to match the version in the index
> -or the specified tree.  If no pathspec was given, `git checkout` will
> -also update `HEAD` to set the specified branch as the current
> -branch.
> +`git checkout` has two main modes: it can
> +**switch branches**, for example with `git checkout <branch>`, and
> +**restore files from a different version**, for example with
> +`git checkout <commit> <filename>` or `git checkout <filename>`
> +
> +See ARGUMENT DISAMBIGUATION below for how Git decides which one to do.
>  
>  `git checkout [<branch>]`::
>  	To prepare for working on _<branch>_, switch to it by updating
> @@ -511,14 +513,17 @@ $ git log -g -2 HEAD
>  ARGUMENT DISAMBIGUATION
>  -----------------------
>  
> -When there is only one argument given and it is not `--` (e.g. `git
> -checkout abc`), and when the argument is both a valid _<tree-ish>_
> -(e.g. a branch `abc` exists) and a valid _<pathspec>_ (e.g. a file
> -or a directory whose name is "abc" exists), Git would usually ask
> -you to disambiguate.  Because checking out a branch is so common an
> -operation, however, `git checkout abc` takes "abc" as a _<tree-ish>_
> -in such a situation.  Use `git checkout -- <pathspec>` if you want
> -to checkout these paths out of the index.
> +When you run `git checkout <something>`, Git tries to guess whether
> +`<something>` is intended to be a branch, a commit, or a set of file(s),
> +and then switches branches, switches commits, or restores the files.

"Switches branches" I can understand.  You were on your old branch
(your HEAD usually is pointing at some branch), and you move to your
new branch by making it your "current" branch.

I do not understand "switches commits".  When you move to a commit
(i.e. your HEAD can point directly at a commit without referring to
any branch), are you switching one commit with another?  I do not
think users would view it that way.

Phrasing it with "switch to" may make it easier to handle.  Then
your previous state would not matter as much.

    ... and then switch to the named branch or the named commit, or
    restores the files in the working tree (i.e. overwrites them
    from different versions).

perhaps.

> +If there's any ambiguity, Git will treat `<something>` as a branch or
> +commit, but you can use the double dash `--` to force Git to treat the
> +parameter as a list of files and/or directories, like this:
> +
> +----------
> +git checkout -- file.txt
> +----------

Good.

>  
>  EXAMPLES
>  --------

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, "Julia Evans" wrote (reply to this):

> You seem to have forgotten to update the proposed log message ...
>
> https://lore.kernel.org/git/[email protected]/
>
> ... to avoid making it just an enumeration of "these random things
> were done in this patch" (and instead tell a coherent story).

Thanks for the reminder, will work on that. I just realized today that I can
use `lazygit` to make it much faster to edit my log messages :)

> I do not understand "switches commits".  When you move to a commit
> (i.e. your HEAD can point directly at a commit without referring to
> any branch), are you switching one commit with another?  I do not
> think users would view it that way.
>
> Phrasing it with "switch to" may make it easier to handle.  Then
> your previous state would not matter as much.

Agreed that "switches commits" is weird, will use "switches to".

**restore files from a different version**, for example with
`git checkout <commit> <filename>` or `git checkout <filename>`

See ARGUMENT DISAMBIGUATION below for how Git decides which one to do.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Junio C Hamano wrote (reply to this):

"Julia Evans via GitGitGadget" <[email protected]> writes:

>  `git checkout [<branch>]`::
> -	To prepare for working on _<branch>_, switch to it by updating
> -	the index and the files in the working tree, and by pointing
> -	`HEAD` at the branch. Local modifications to the files in the
> -	working tree are kept, so that they can be committed to the
> -	_<branch>_.
> +	Switch to _<branch>_. This sets the current branch to <branch> and
> +	updates the files in your working directory. Local changes to
> +	the files in the working tree are kept, so that they can be committed
> +	to the _<branch>_. If the local changes can't be cleanly merged into
> +	the _<branch>_, no changes will be made and the checkout operation will fail.

The condition to stop you is a bit stronger than that.

By default, we would not even attempt to "merge into the branch" at
all.  If your previous HEAD and the branch you are switching to are
different at a path you have local modifications in, then no changes
will be made and the checkout will fail.  With "-m", we try to merge
and this merge can leave conflicts for you to sort out.

> @@ -42,10 +42,8 @@ exactly one remote (call it _<remote>_) with a matching name and
>  $ git checkout -b <branch> --track <remote>/<branch>
>  ------------
>  +
> -You could omit _<branch>_, in which case the command degenerates to
> -"check out the current branch", which is a glorified no-op with
> -rather expensive side-effects to show only the tracking information,
> -if it exists, for the current branch.
> +Running `git checkout` without specifying a branch has no effect except
> +to print out the tracking information for the current branch.

This is much better than the crappy original I wrote years ago.
Thanks.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, "Julia Evans" wrote (reply to this):

> The condition to stop you is a bit stronger than that.
>
> By default, we would not even attempt to "merge into the branch" at
> all.  If your previous HEAD and the branch you are switching to are
> different at a path you have local modifications in, then no changes
> will be made and the checkout will fail.  With "-m", we try to merge
> and this merge can leave conflicts for you to sort out.

Thanks, I wasn't sure based on the existing text what
"modifications are kept" meant exactly, and I've always been slightly
hazy about this behaviour. Will fix.

@@ -54,18 +54,17 @@ if it exists, for the current branch.
`--track` without `-b` implies branch creation; see the
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Junio C Hamano wrote (reply to this):

"Julia Evans via GitGitGadget" <[email protected]> writes:

> From: Julia Evans <[email protected]>
>
> Many Git users don't know what the term "reset" means. Resolve this by:

Even though it is the name of one of the most often used commands?
And yet a separate step in this series made the claim that everybody
knows what "switch" means because it is the name of another command?

I think the source of the problem is not that they "don't know what
the term means" at all.  Isn't the real problem that the use of the
verb in the original sentence you are correcting in this patch is
vague and does not say what the branch is reset *to*?

> - Expanding it into its definition, in one case

    The description says "-B <branch>" resets the branch if it
    exists, but does not say what it resets to.  Rephrase to clarify
    that it is made to point at the specified commit.

or something?

> - Giving a simpler but still accurate explanation ("the branch will not
>   be created or modified"), in the other case

By the way this kind of use of bulleted list in a proposed log
message I do not mind all that much.  What I reacted to was a list
without the introducing text (in the case of this patch, "resolve
this by doing these things:").
>
> Signed-off-by: Julia Evans <[email protected]>
> ---
>  Documentation/git-checkout.adoc | 11 +++++------
>  1 file changed, 5 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/git-checkout.adoc b/Documentation/git-checkout.adoc
> index 4de3ac6680..e4614674f0 100644
> --- a/Documentation/git-checkout.adoc
> +++ b/Documentation/git-checkout.adoc
> @@ -54,18 +54,17 @@ to print out the tracking information for the current branch.
>  	`--track` without `-b` implies branch creation; see the
>  	description of `--track` below.
>  +
> -If `-B` is given, _<new-branch>_ is created if it doesn't exist; otherwise, it
> -is reset. This is the transactional equivalent of
> +If `-B` is given, _<new-branch>_ is created if it doesn't exist;
> +otherwise `<new-branch>` is forced to point at the commit. ...

Good.

> ... This is the
> +transactional equivalent of
>  +
>  ------------
>  $ git branch -f <branch> [<start-point>]
>  $ git checkout <branch>
>  ------------
>  +
> -that is to say, the branch is not reset/created unless "git checkout" is
> -successful (e.g., when the branch is in use in another worktree, not
> -just the current branch stays the same, but the branch is not reset to
> -the start-point, either).
> +that is, the branch will not be created or modified unless
> +`git checkout` is successful.
>  
>  `git checkout --detach [<branch>]`::
>  `git checkout [--detach] <commit>`::

This is in response to "transactional equivalent".  I've always felt
that there is no need to say "transactional" in this at all.  IOW, I
wouldn't have minded if we rewrote this more heavily.

When you have to clarify with things like "that is", "what this
means is", etc., after some text, I've often found that the result
becomes crispier and more clear if we removed fuzzy text that needed
such clarification and rewrite the sentence using elements form only
the clarifying text.

    If `-B` is given, _<new-branch>_ is created if it doesn't exist,
    otherwise, it is made to point at the given commit.  And the
    branch is made the current branch.
    +
    Creation of the new branch or reseting of the existing branch to
    point at the commit happens only if the resulting branch can be
    successfully checked out.  Oterwise branch creation is not done
    and the exiting branch is left as-is.

or something?  I dunno.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, "Julia Evans" wrote (reply to this):

> I think the source of the problem is not that they "don't know what
> the term means" at all.  Isn't the real problem that the use of the
> verb in the original sentence you are correcting in this patch is
> vague and does not say what the branch is reset *to*?

I agree this is a reasonable approach here, will try that.

>> Many Git users don't know what the term "reset" means. Resolve this by:
>
> Even though it is the name of one of the most often used commands?
> And yet a separate step in this series made the claim that everybody
> knows what "switch" means because it is the name of another command?

I'm surprised to hear you say that "reset" is one of the most often
used Git commands -- what I frequently hear from Git users is that they
use `git reset` only in "emergencies" where something has gone wrong
and that they're afraid of using it.

I'm curious about whether there are any datasets about which Git
commands are the most frequently used, or if it would be worth me
trying to build one.

>> ... This is the
>> +transactional equivalent of
>>  +
>>  ------------
>>  $ git branch -f <branch> [<start-point>]
>>  $ git checkout <branch>
>>  ------------
>>  +
>> -that is to say, the branch is not reset/created unless "git checkout" is
>> -successful (e.g., when the branch is in use in another worktree, not
>> -just the current branch stays the same, but the branch is not reset to
>> -the start-point, either).
>> +that is, the branch will not be created or modified unless
>> +`git checkout` is successful.
>>  
>>  `git checkout --detach [<branch>]`::
>>  `git checkout [--detach] <commit>`::
>
> This is in response to "transactional equivalent".  I've always felt
> that there is no need to say "transactional" in this at all.  IOW, I
> wouldn't have minded if we rewrote this more heavily.

"Transactional equivalent" was bothering me too and I like the
idea of rewriting it, will give it a shot.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Junio C Hamano wrote (reply to this):

"Julia Evans" <[email protected]> writes:

> I'm surprised to hear you say that "reset" is one of the most often
> used Git commands -- what I frequently hear from Git users is that they
> use `git reset` only in "emergencies" where something has gone wrong
> and that they're afraid of using it.

For the list of commands that have been historically considered
"common":

    $ git -h

is meant to serve a good guide.  We may want to cull/update some
entries (like, "backfill" which should not be more prominent than
"maintenance", for example), but I think it is not far off or way
too stale (for one thing, it no longer lists checkout but gives two
separate commands, restore and switch, which are no longer marked as
experimental).

>>>  `git checkout --detach [<branch>]`::
>>>  `git checkout [--detach] <commit>`::
>>
>> This is in response to "transactional equivalent".  I've always felt
>> that there is no need to say "transactional" in this at all.  IOW, I
>> wouldn't have minded if we rewrote this more heavily.
>
> "Transactional equivalent" was bothering me too and I like the
> idea of rewriting it, will give it a shot.

Thanks.

Copy link

gitgitgadget bot commented Aug 29, 2025

There was a status update in the "New Topics" section about the branch je/doc-checkout on the Git mailing list:

Doc updates.
source: <[email protected]>

Copy link

gitgitgadget bot commented Sep 2, 2025

There was a status update in the "Cooking" section about the branch je/doc-checkout on the Git mailing list:

Doc updates.
source: <[email protected]>

Copy link

gitgitgadget bot commented Sep 2, 2025

This patch series was integrated into seen via git@f9c79e1.

Copy link

gitgitgadget bot commented Sep 2, 2025

This patch series was integrated into seen via git@03a7651.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant