I'd rephrase and simplify this article a bit.<p>`git switch` and `git restore` are better alternatives to the `git checkout` command, as they have a lower cognitive overhead and fewer footguns to avoid. Although these commands are marked in the documentation as experimental, they work extremely well in practice. Experimental in this sense means that these may gain or lose behavior over time, not that these commands are unstable for use. As a community, we should use `switch` and `restore` commands rather than `checkout` when documenting / teaching git so that newer users start with a greater ability to reason about how the commands affect their workflow.<p>For more about the introduction of these commands and the details of the above see <a href="https://github.blog/open-source/git/highlights-from-git-2-23/#experimental-alternatives-for-git-checkout" rel="nofollow">https://github.blog/open-source/git/highlights-from-git-2-23...</a>
Checkout is fine; it makes sense when you realize that the entire point of checkout is that it updates your current working tree to whatever you instruct it to. What "whatever" is: it's anything that git can understand as a reference; branch names (including those on remotes), commit IDs, HEAD and offsets (carets) on top of any of them.<p>ie. If you do "checkout master" it will checkout your working tree to the master branch. If you do "checkout HEAD", you get whatever's the current HEAD of your repository (in practice, this discards your changes).<p>Checkout can also do a partial checkout on a specific part of your working tree; "checkout [filename]" makes it so that you update that specific file to how it is on whatever you point it at.<p>The only weirdness is "checkout -b [branch]" making a new branch and switching you to it. It's a bit syntactically off/breaks the previous thing, but makes a lot of sense when you realize that your average workflow will combine git branch and git checkout anyway (since you're pretty much always making a branch to them work on it.)<p>Git switch and restore both feel like syntactic sugar that doesn't really help enough to warrant the mental switch of going from checkout to switch/restore. (Not to mention that checkout and restore do different things; restore also merged some functionality from git reset, a command whose main purpose is to update the index.)
Some things bug me in checkout; it should never have had a -b option so that it does "git branch" things along with checking out. It was probably done that way because early in Git's development, there was a lot of fuss about it having light weight branching, and what looks even more light weight is when you can instantly create a branch and switch to it with one command.<p>There is a consistency in <i>checkout</i> and <i>reset</i>.<p>Both checkout and reset can be <i>whole</i> or <i>partial</i> (terms I made up). Partial checkouts and resets specify paths. Whole specify at most a revision.<p>The checkout operation updates the indexed and working copies of files to be like what is specified in a given revision.<p>- A whole checkout to another revision, if it succeeds, will update the working files and index to what is in that revision, and move HEAD to it.<p>- A partial checkout updates the specified files, working and index, to what they look like in the given revision, without moving HEAD.<p>- A whole reset to to another revision updates just the index to that revision, and moves the current branch and HEAD to it. Working files stay the same.<p>- A partial reset updates the index entries for the specified files, to the given revision, without moving HEAD or branch. Working files stay the same.<p>There are obviously more details, due to various options like reset --hard and so on, plus considerations of what happens with a dirty index. But that's the basic paradigm:<p><pre><code> (starting with clean tree)
checkout reset
whole moves: HEAD moves: HEAD and branch
updates: working + index updates: index
result: clean result: working diff, nothing staged
partial moves: nothing moves: nothing
updates: working + index updates: index
result: working diff, staged result: working diff, opposite change staged
</code></pre>
The basic consistencies are:<p>- the partial operations don't move the HEAD or current branch in both cases; the whole operations do move HEAD or HEAD + branch.<p>- whole or partial checkout updates working + index.<p>- whole or partial reset updates index.
Wholeheartedly agree with this suggestion.<p>I don't think I have used the incomprehensible `checkout` command once since I learned that `switch` and `restore` exist, and the previous years-long state of perpetual low-grade irritation I had felt toward git has diminished accordingly.
> … the only way to really understand deeply how git checkout works, you have to fundamentally understand the internal workings of git.<p>This is, and always has been, the primary UX problem with git. You use commands to manipulate the program’s model of the data, rather than to demonstrate your intent. It works only as long as your mental model of git matches git itself, but it doesn’t easily afford abstraction, and abstraction is the essence of efficient manipulation.<p>Put another way, a good tool allows you to use it well even if you don’t understand how it works. Git OTOH will quickly punish you for not understanding its model of the world.<p>A good UX for git would maintain the complexity for experts and provide a clear and simple surface area for most people who just want to perform familiar tasks. The fact that each person and team seems to have a unique incantation just for everyday tasks is an awful smell, and a sign of git’s immaturity.
The article writes:<p>> they had not asked me to explain git, they had asked me to explain GitHub<p>This is often the case for me as well.<p>Hey, at least git owns it by calling the shell commands "porcelain" (with git itself being the plumbing -- <a href="https://stackoverflow.com/questions/6976473/what-does-the-term-porcelain-mean-in-git" rel="nofollow">https://stackoverflow.com/questions/6976473/what-does-the-te...</a> ).<p>The core value proposition of GitHub, GitLab, etc is to provide a nice GUI atop git. That's huge. I think that user-studies to improve one of the many existing foss git GUIs would be much better use of brain than deprecating git checkout.
checkout is one of the few git commands that makes sense to me. I use it a lot, to get back to a known state, after I screw up my working files with other git commands. E.g.<p>Copy my changed files to a temporary directory.<p>Delete my working directory.<p>Checkout the latest version from the repo.<p>Copy my changed files back.
I am so deeply pissed off at people who look at some completely useful, universal, widely-used-for-decades canonical command that's at the center of tens of millions of manual and automated deployments, picks out some esoteric details they decide are important and then proclaim, "OK when can we <i>deprecate</i> this debacle?" People who think you can just point "DEPRECATE" around at anything that they've decided is distasteful like a magic wand show their deep inexperience in tech as well as life overall and have no business making such proclamations.
I'm surprised no one has mentioned what is in my mind the cardinal sin of checkout: the parameter can be either a path or a ref and it automatically infers which one you mean. That's magic and relies on your ref namespace and your file namespace not conflicting (of course you can be explicit but no one is)<p>I think if the "only operate on certain files" mode of checkout was a flag, it would be much less confusing and easier to explain and we never would have gotten into this mess to begin with.
Hm. It doesn't look like git checkout does "too many things" or is overly complicated. It does one thing basically, which is changing the files in your working directory. It can work on single files or on the whole working directory, and it can optionally shortcut the creation of a new branch.<p>Then again, until today I never knew about "git switch" so I, too, learned something today :)
Maybe I am a rube, but people bemoaning "complexity" of git just never strikes home with me. I started using it when I was 14, so maybe that is it (it was still fairly new, but it's all I've ever known) - I still only use a handful of commands.<p>git checkout, git checkout -b<p>git pull<p>git merge (mostly to merge master back into a development branch, or something like that)<p>git push<p>git restore (much more rarely)<p>git reset (even much more rarely)<p>Barely ever have I had to do anything but these for 99.999% of my workflow, and none of them seem particularly complicated unless you run into merge conflicts, but on every team there seems to be at least one pro "merge conflict" guy. Idk. Checkout is occasionally annoying when it forces you to stash unrelated changes to what you're doing, that's about all I can come up with.
Never have I read Git Pro or have the deep understanding of git’s internals. But I use checkout almost every day, as a shortcut to create a new branch and switch to it, throw away changes that I don’t need and…well, that’s pretty much it.<p>Now that I have read this article half way, I decided to stop. Because I am learning a few extra things that’s kind of messing up my mental model of what that command does. I think a fair % of git users might be in my boat. Our knowledge, hence our burden is limited.<p>So community might not be as confused with checkout as the author or those who grok git.
I wanted to stop using git checkout, so I set up a little .bashrc magic to prevent me from calling 'git checkout' and to suggest which command I <i>should</i> be using instead. Here's the script:<p><pre><code> # Paste this snippet into your .bashrc to help you learn `git switch`.
#
# Turn on the extdebug mode so that our `scold_git_checkout` can prevent
# us from running git-checkout by exiting 1; forcing us to re-learn our
# muscle memory.
# If we *really* need to use git checkout for something, we can do that
# by using the full path to the git executable e.g.:
# /usr/bin/git checkout # isn't caught by our scolding
shopt -s extdebug
scold_git_checkout() {
if [ "$1" != "git" ]; then
return 0
fi
if [ "$2" != "checkout" ]; then
return 0
fi
cat >&2 <<EOF
////// DON'T use git checkout! //////
The 'git checkout' command of git has been replaced with two other
commands: 'git switch' and 'git restore'. You used:
$@
EOF
if [ "$3" == "-b" ]; then
PASTESAFE="$(printf "%q " "${@:4}")"
cat >&2 <<EOF
You should use the following:
git switch -c $PASTESAFE
EOF
elif [ "$3" == "--" ]; then
PASTESAFE="$(printf "%q " "${@:4}")"
cat >&2 <<EOF
You should use the following:
git restore $PASTESAFE
EOF
else
PASTESAFE="$(printf "%q " "${@:3}")"
cat >&2 <<EOF
You can try the following:
git switch $PASTESAFE
EOF
fi
return 1
}
trap 'scold_git_checkout $BASH_COMMAND' DEBUG
</code></pre>
Gist with this special scold commit hook, should I ever change it more: <a href="https://gist.github.com/lelandbatey/b42b527bfa41b761d0aec2871d32748a" rel="nofollow">https://gist.github.com/lelandbatey/b42b527bfa41b761d0aec287...</a>
The title and first 2/3s of the article are excessively hyperbolic and it detracts from the message. The title would be improved by adding "in favor of git switch/restore". The body would be improved by leading with the last 3 paragraphs, and tucking the rest under a "why not just use `git checkout`?" section.<p>I appreciated finding out about `switch` and `restore` as alternatives to `checkout`. But they are minor, incremental improvements. Framing it like `checkout` is the devil doesn't help, because it really isn't that bad, especially to people who consider git as a means to an end.
It's not hard to change to git switch. I used to have a "co" alias for "checkout" which I removed. I'd say I lost maybe 60 seconds of typing time over the few weeks it took to unlearn the muscle memory.<p>60 seconds of time investment to be better at mentoring the next generation of technologists is worth it.
I am horrified by the article's last paragraph.<p>Teach RESET instead of checkout???<p>The command with the most likelihood to make you lose work, and leave you with permanent errors??<p>And with the most convoluted usage and documentation?
What is wrong with me that I dont have any problems with this? Maybe it’s how we name branches? I think I’ve only seen a few cases where I use checkout and it complains about being ambiguous.
Huh. I use checkout multiple times a day every day. It's how I switch branches, including creating new branches. I guess I could use other commands, but why change what's working fine?
The crux of it, and the reason why I see it as a lost cause:<p>> the only way to really understand deeply how git checkout works, you have to fundamentally understand the internal workings of git.<p>Thing is, there's no way around fundamentally understanding the internal workings if you're going to use git on the command line.<p>Checkout and reset can be tough, but for instance reflog also makes no sense if you don't understand the commit model.<p>Newer user and occasional git users will be better served with a nice GUI. VSCode has extensions that will help deal with the basic operations etc.<p>The issue to me has never been that commands are cryptic, and more that git isn't made for people enjoying simplicity. For those, an extra layer above git is the best choice IMHO.
Git is not that complicated. If you can't grok git I am seriously concerned about your ability to be an effective software engineer.<p>Edit: I had assumed the OP was one of the many people I have met who have a Tech Lead title but are not really very technical due to the grandiose request to deprecate checkout. But looking into the blog more I realize that instead the author is more new in their career and I don't mean to be as harsh to someone in that position. Instead to them I would say; when you encoutner something established you don't understand, take it as an opportunity to learn. Git isn't beyond you, it won't take as long to fully understand as you think.