git: prefer switch over checkout
• 381 words • 2 min • updated
What’s the difference between ‘git switch’ and ‘git checkout’
? Git 2.23 introduces a new command
git switch. After reading the documentation, it seems pretty much the same asgit checkout <branchname>. What is the difference or use case?
git switchcan now be used to change branches, as git checkoutdoes People are confused by these different ways to use git checkout, as you can see from the many questions regarding git checkout here on Stack Overflow. Git developers seem to have taken this into account.
git switch is the idiomatic way
to switch branches these days. git checkout can be ambiguous; not only it
switches branches, it can also revert/reset files and directories.
I unexpectedly hit this ambiguity today.
I have this git bd alias:
% grep -E '(bd|default\b)' ~/.gitconfig
bd = !branch="$(git branch --show-current)" && git default && git branch -D "${branch:-$1}"
default = !git checkout main &>/dev/null || git checkout master…which is short for “branch delete”.
Example: I am working on branch thiagowfx/my-branch, then the commit/PR is
eventually merged. My next action is git bd, which a) switches to the default
branch (main or master these days) and b) deletes the previous branch.
This works well most of the time.
Today, when
bumping
the yamlfmt
package for
Alpine Linux, I was in the yamlfmt branch and then ran git bd.
That didn’t do anything. Here’s the problem:
% tree -L 1
.
├── CODINGSTYLE.md
├── COMMITSTYLE.md
├── README.md
├── community
├── main
├── scripts
└── testing…there’s a main/ directory in the repository root.
Thus git default, which calls git checkout main, treats main as a
directory in this context, instead of a branch.
One solution is to call git checkout main -- instead, which explicitly denotes
main as a branch1. However, that’s hard to remember and it’s also
confusing. It’s easier to simply do git switch main.
So here’s my updated alias, which works as originally intended:
% grep -E '(bd|default\b)' ~/.gitconfig
bd = !branch="$(git branch --show-current)" && git default && git branch -D "${branch:-$1}"
default = !git switch main &>/dev/null || git switch master-
To explicitly denote it as a directory / file, call
git checkout -- maininstead. I use this variant often to revert file modifications back to the original state. ↩︎