Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 76 additions & 75 deletions Documentation/git-checkout.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,29 @@ git checkout [-q] [-f] [-m] [<branch>]
git checkout [-q] [-f] [-m] --detach [<branch>]
git checkout [-q] [-f] [-m] [--detach] <commit>
git checkout [-q] [-f] [-m] [[-b|-B|--orphan] <new-branch>] [<start-point>]
git checkout [-f] <tree-ish> [--] <pathspec>...
git checkout [-f] <tree-ish> --pathspec-from-file=<file> [--pathspec-file-nul]
git checkout <tree-ish> [--] <pathspec>...
git checkout <tree-ish> --pathspec-from-file=<file> [--pathspec-file-nul]
git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [--] <pathspec>...
git checkout [-f|--ours|--theirs|-m|--conflict=<style>] --pathspec-from-file=<file> [--pathspec-file-nul]
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.

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

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 Fri, Aug 29, 2025 at 5:00 PM Junio C Hamano <[email protected]> wrote:
>
> "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.

I'd say your first version matches my concept of that mode, but it's
heavy on the operation (do this, do that) vs the declaration (desired
end state). Of course the second version still has the verb "update,"
but we emphasize less "how" to update and more the results of said
update?

> Anyway, thanks for a review.

:)

-- 
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):

"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".

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.
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.


`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. The checkout will fail
if there are uncommitted changes to any files where _<branch>_ and
your current commit have different content. Uncommitted changes will
otherwise be kept.
+
If _<branch>_ is not found but there does exist a tracking branch in
exactly one remote (call it _<remote>_) with a matching name and
Expand All @@ -40,68 +44,63 @@ 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.

`git checkout (-b|-B) <new-branch> [<start-point>]`::

Specifying `-b` causes a new branch to be created as if
linkgit:git-branch[1] were called and then checked out. In
this case you can use the `--track` or `--no-track` options,
which will be passed to `git branch`. As a convenience,
`--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
+
------------
$ git branch -f <branch> [<start-point>]
$ git checkout <branch>
------------
Running `git checkout` without specifying a branch has no effect except
to print out the tracking information for the current branch.

`git checkout -b <new-branch> [<start-point>]`::

Create a new branch named _<new-branch>_, start it at _<start-point>_
(defaults to the current commit), and check out the new branch.
You can use the `--track` or `--no-track` options to set the branch's
upstream tracking information.
+
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).
This will fail if there's an error checking out _<new-branch>_, for
example if checking out the `<start-point>` commit would overwrite your
uncommitted changes.

`git checkout -B <branch> [<start-point>]`::

The same as `-b`, except that if the branch already exists it
resets `_<branch>_` to the start point instead of failing.

`git checkout --detach [<branch>]`::
`git checkout [--detach] <commit>`::

Prepare to work on top of _<commit>_, by detaching `HEAD` at it
(see "DETACHED HEAD" section), and updating the index and the
files in the working tree. Local modifications to the files
in the working tree are kept, so that the resulting working
tree will be the state recorded in the commit plus the local
modifications.
+
When the _<commit>_ argument is a branch name, the `--detach` option can
be used to detach `HEAD` at the tip of the branch (`git checkout
<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>...`::
`git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] --pathspec-from-file=<file> [--pathspec-file-nul]`::
`git checkout <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:

> -	Overwrite both the index and the working tree with the
> -	contents at the _<tree-ish>_ for the files that match the pathspec.
> +	Replace the specified files and/or directories with the version from
> +	the given commit or tree and stage the files' contents.

Hmph.  I agree that there is no reason to stress that you are not
required to use a commit here (hence not much point in saying
tree-ish).  I do not think avoiding "index" (which is not even a
jargon; it is the official name of the thing) is necessarily a good
idea, given that ...

> +For example, `git checkout main file.txt` will replace `file.txt`
> +with the version from `main`.
>  
>  `git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [--] <pathspec>...`::
>  `git checkout [-f|--ours|--theirs|-m|--conflict=<style>] --pathspec-from-file=<file> [--pathspec-file-nul]`::
>  
> -	Overwrite working tree with the contents in the index for the files
> -	that match the pathspec.
> +	Discard any unstaged changes to the specified files and/or directories.
> +	This works by copying the file from the index to your working directory.
> +	For example, `git checkout file.txt` will replace `file.txt` with either
> +	the staged version of `file.txt` (if there is one) or the version from the
> +	current commit.

... we'd have to say "from the index to your working tree files"
here.  In contrast, the earlier one is "from the commit to the index
and to your working tree files", and explaining it as such may make
the similarity & differences stand out more clearly.

Also, I personally find it easier to follow if you did
"directories. This works by copying" -> "directories, by copying".
It comes from the same "think again when you find that you are
saying 'it means that' and such" principle.

> +This will fail if the file has a merge conflict and you haven't yet run
> +`git add file.txt` (or something equivalent) to mark it as resolved.
> +You can use `-f` to ignore the unmerged files instead of failing, use
> +`--ours` or `--theirs` to replace them with the version from a specific
> +side of the merge, or use `-m` to replace them with the original
> +conflicted merge result.

OK.

`git checkout <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>_.
Replace the specified files and/or directories with the version from
the given commit or tree and add them to the index
(also known as "staging area").
+
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
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.
For example, `git checkout main file.txt` will replace `file.txt`
with the version from `main`.

`git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [--] <pathspec>...`::
`git checkout [-f|--ours|--theirs|-m|--conflict=<style>] --pathspec-from-file=<file> [--pathspec-file-nul]`::

Replace the specified files and/or directories with the version from
the index.
+
For example, if you check out a commit, edit `file.txt`, and then
decide those changes were a mistake, `git checkout file.txt` will
discard any unstaged changes to `file.txt`.
+
This will fail if the file has a merge conflict and you haven't yet run
`git add file.txt` (or something equivalent) to mark it as resolved.
You can use `-f` to ignore the unmerged files instead of failing, use
`--ours` or `--theirs` to replace them with the version from a specific
side of the merge, or use `-m` to replace them with the original
conflicted merge result.

`git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>...]`::
This is similar to the previous mode, but lets you use the
This is similar to the previous two modes, but lets you use the
interactive interface to show the "diff" output and choose which
hunks to use in the result. See below for the description of
`--patch` option.
Expand Down Expand Up @@ -155,16 +154,14 @@ of it").
see linkgit:git-branch[1] for details.

`-B <new-branch>`::
Creates the branch _<new-branch>_, start it at _<start-point>_;
if it already exists, then reset it to _<start-point>_. And then
check the resulting branch out. This is equivalent to running
`git branch` with `-f` followed by `git checkout` of that branch;
see linkgit:git-branch[1] for details.
The same as `-b`, except that if the branch already exists it
resets `_<branch>_` to the start point instead of failing.

`-t`::
`--track[=(direct|inherit)]`::
When creating a new branch, set up "upstream" configuration. See
`--track` in linkgit:git-branch[1] for details.
`--track` in linkgit:git-branch[1] for details. As a convenience,
--track without -b implies branch creation.
+
If no `-b` option is given, the name of the new branch will be
derived from the remote-tracking branch, by looking at the local part of
Expand Down Expand Up @@ -511,14 +508,18 @@ $ 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 either switches to that branch or commit, or restores the
specified files.

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
----------

EXAMPLES
--------
Expand Down
Loading