What's the difference between git switch and git checkout <branch>
Well, according to the documentation you link to, its sole purpose is to split and clarify the two different uses of git checkout
:
-
git switch
can now be used to change branches, asgit checkout <branchname>
does -
git restore
can be used to reset files to certain revisions, asgit checkout --<path_to_file>
does
People are confused by these different ways to use git checkout
, as you can see from the many questions regarding git checkout
here on Stackoverflow. Git developers seem to have taken this into account.
git checkout
is a bit of a swiss army knife in that has several unrelated uses.
If you modify a file but haven't staged the change, then git checkout <filename>
will reverse the modifications... a quick and easy way to cancel changes to a file. You remain in the same branch.
git checkout <branchname>
(as you noted) switches branches.
Two completely different purposes, which could lead to confusion if a file name and a branch name are similar.
Having it as two commands is clearer.
As you noted in the 2.23.0 release notes section you quoted, the switch
and restore
commands were introduced to split the checkout
command into two separate pieces:
- "checking out a branch to work on advancing its history"
- "checking out paths out of the index and/or a tree-ish to work on advancing the current history"
In other words, checkout
was doing two different things, and this release splits each of those different things into its own focused command.
This dual purpose of checkout
can be seen in its summary description in the documentation:
git-checkout - Switch branches or restore working tree files
The commit message for the commit that added the switch
command explains the rationale:
"git checkout" doing too many things is a source of confusion for many users (and it even bites old timers sometimes). To remedy that, the command will be split into two new ones: switch and restore. The good old "git checkout" command is still here and will be until all (or most of users) are sick of it.
From this, it's clear that the new commands were introduced to reduce confusion by having two focused commands, rather than one multi-purpose command.
Note that as of December 2021, the new commands are still listed as experimental (switch
, restore
):
THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
Command comparison
I have not found a full comparison of the commands anywhere. From reading through the documentation, I think this should be a fairly complete comparison:
previous command | new command |
---|---|
git checkout <branch> |
git switch <branch> |
git checkout |
N/A (use git status ) |
git checkout -b <new_branch> [<start_point>] |
git switch -c <new-branch> [<start-point>] |
git checkout -B <new_branch> [<start_point>] |
git switch -C <new-branch> [<start-point>] |
git checkout --orphan <new_branch> |
git switch --orphan <new-branch> |
git checkout --orphan <new_branch> <start_point> |
N/A (use git switch <start-point> then git switch --orphan <new-branch> ) |
git checkout [--detach] <commit> |
git switch --detach <commit> |
git checkout --detach [<branch>] |
git switch --detach [<branch>] |
git checkout [--] <pathspec>… |
git restore [--] <pathspec>… |
git checkout --pathspec-from-file=<file> |
git restore --pathspec-from-file=<file> |
git checkout <tree-ish> [--] <pathspec>… |
git restore -s <tree> [--] <pathspec>… |
git checkout <tree-ish> --pathspec-from-file=<file> |
git restore -s <tree> --pathspec-from-file=<file> |
git checkout -p [<tree-ish>] [--] [<pathspec>…] |
git restore -p [-s <tree>] [--] [<pathspec>…] |
As shown in this comparison, some prior usages can be simply converted to the new commands by replacing the old command name (checkout
) to the new one (switch
, restore
), whereas others require additional adjustment. Notable changes include:
- The
-b
/-B
options for creating a new branch before switching are renamed to-c
/-C
-
--detach
is now always required when switching to a detached head, where it was previously optional for commits but required for branches - The source tree for restoring is now given by the
-s
option, rather than being an inline argument
switch
has some limitations: at the moment you can switch from any commit to <branch name>
, however it's impossible to switch from <branch name>
to a particular commit with a status of detached HEAD. So you need to use git checkout 5efb
(where 5efb is an example of a hash reference to arbitrary commit)
here is an extract from the git manual — man git-switch
.
Synopsis
git switch [<options>] [--no-guess] <branch> git switch [<options>] --detach [<start-point>] git switch [<options>] (-c|-C) <new-branch> [<start-point>] git switch [<options>] --orphan <new-branch>
Description
Switch to a specified branch. The working tree and the index are updated to match the branch. All new commits will be added to the tip of this branch.
Optionally a new branch could be created with either
-c
,-C
, automatically from a remote branch of same name (see--guess
), or detach the working tree from any branch with--detach
, along with switching.Switching branches does not require a clean index and working tree (i.e. no differences compared to
HEAD
). The operation is aborted however if the operation leads to loss of local changes, unless told otherwise with--discard-changes
or--merge
.THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.