Can we communally deprecate git checkout?
148 comments
·January 9, 2025cmgriffing
I feel like the value of changing from `git checkout -b` to `git switch -c` is not worth the cognitive overhead of making the change.
kedean
Not to mention the official docs for "switch" still state "THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE."
ghewgill
Yes. This warning in the documentation (and the same warning for "git restore") is doing nothing to help the situation. I've had to put a stake in the ground on this SO answer: https://stackoverflow.com/a/215731/893
epistasis
> [At the time of writing, the git restore command has been marked as "experimental" for at least four years.]
Honestly I have not bothered to even learn switch or restore because of these warnings. If they keep them in after five years, then the commands might be removed in the next version, because clearly there's no champion behind them pushing them forward.
And the few times I have tried to learn what they do, I have not seen any benefit over my current knowledge. So why learn something that may go away and is not trusted even five years and many many versions after deployment?
Izkata
This goes well with my experience from svn where "svn switch" had a high-enough chance to screw up your checkout that everyone I know just had multiple checkouts instead.
BizarreByte
I felt that way about the master to main debacle, but some angry people online won anyway.
disgruntledphd2
The irritating thing about that is that the software git defaults to master, while GitHub defaults to main. I had a lot of confusion a few months back about that.
two_cents
You can set default branch name for your repositories in settings. Much more straightforward than in GitLab in my opinion.
joshka
I made that exact thought many years ago and came to the direct opposite conclusion. It was worth the cognitive overhead to make the change and I haven't looked back. Most of the time I'm just hitting aliases (from OMZ's git plugin) https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/git e.g.
gsw git switch
gswc git switch -c
gswd git switch $(git_develop_branch)
gswm git switch $(git_main_branch)
imoreno
Do people really type these out, instead of just making a bash alias?
camtarn
Used to have bash aliases, but nowadays I work on so many different machine, without my dotfiles present, that aliases seem kinda pointless. I'm a fast typist.
dwaltrip
I would wager that 90% of people using git don’t have bash aliases.
g-b-r
I would wager that above 90% (of those using command-line git) do, after at most a few weeks of heavy git usage
It takes no time to add some, and it's not necessary to put them online and synchronize them; it would be a no-brainer for me to add some manually, if I had to work on a new machine for more than a few minutes (and couldn't access my usual ones from it)
moregrist
Aliases have always been a double-edged sword.
They're shorter and let you be more efficient at common tasks.
They also tend to be personal and hard to share. Which can make it harder to explain what you’re doing to a coworker for pairing/debugging/training purposes. And you have to remember both the aliases and the underlying commands/options, at least enough to remember when you don’t want to use the alias.
I don’t find that I use git subcommands with a frequency that makes me want to alias them. It’s likely that different workflows lead to different optimizations.
remram
I was always using 'co' for checkout. Made the change to switch ('git s') and revert ('git r') and it has been pretty seemless. I do wish 'git reset' defaulted to --keep.
noirscape
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.
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).
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.
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.)
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.)
nayuki
git checkout is not fine.
git checkout <commit> requires a clean working tree, and will change HEAD to the specified <commit>.
git checkout [<commit>] <paths> does not require a clean working tree, will replace the specified paths (i.e. files or directories), and does not change HEAD.
These are extremely different behaviors. I agree with the article that git switch vs. git restore are better replacements.
Since you bring up the topic of git reset, I also disagree with what you said; I don't think its main purpose is to update the index; rather, it is to update the current branch's pointer to an arbitrary commit with the possibility of orphaning children (unlike git commit or git merge, which never lose children). Factually speaking, git reset can update just the branch (--soft), the branch and then index (--mixed), or the branch then index then working tree (--hard). Of course, if you perform git reset and stay at the current HEAD commit, then you have the choice of updating just the index, or the index and the working tree.
fargle
can't upvote this enough. the only (minor) issue i see is the checkout -b shortcut feature is unnecessary and could be confusing if learned before a canonical approach that emphasizes that those are two things - checking something out to the working tree and creating a named branch pointing at it.
other than that, contrary to sibling comments, no the rest of checkout is fine. yes it has guardrails that are perhaps not 100% consistent, but i don't think they every could be. but guardrails or not, when you say `git checkout <versionish>` it trys to checkout the <versionish> version to the working tree. it's highly intuitive that `git checkout <versionish> <filename>` it doesn't do the whole tree, but only that file (excellent for reverting a single file).
i don't want git checkout to be called git switch or any other nonsense. git checkout checks out a version and that is terminology common with just about every cm tool ever.
git reset is a hot mess. the blog post should be about that mess, not checkout.
kazinator
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.
There is a consistency in checkout and reset.
Both checkout and reset can be whole or partial (terms I made up). Partial checkouts and resets specify paths. Whole specify at most a revision.
The checkout operation updates the indexed and working copies of files to be like what is specified in a given revision.
- 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.
- A partial checkout updates the specified files, working and index, to what they look like in the given revision, without moving HEAD.
- 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.
- 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.
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:
(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
The basic consistencies are:- the partial operations don't move the HEAD or current branch in both cases; the whole operations do move HEAD or HEAD + branch.
- whole or partial checkout updates working + index.
- whole or partial reset updates index.
marssaxman
Wholeheartedly agree with this suggestion.
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.
kazinator
What do you use for navigating in the branch history when doing a git bisect? Can you use switch for that?
remram
I think you're asking for 'git switch -d' (for detached).
In practice you will still need 'git reset' but only with a branch parameter (all 'git reset -- paths' can be replaced with 'git restore'), usually with --keep, --soft, or --mixed.
marssaxman
I'm afraid I have no idea - I've never needed to use `git bisect`.
sonofhans
> … the only way to really understand deeply how git checkout works, you have to fundamentally understand the internal workings of git.
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.
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.
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.
makemyworkforme
I must admit that when I first learnt git, I thought that the only way to correctly use git was to know the object model of git. I thought this was important because git is at the end a data manager and I then though that one should know the data model you are manipulating in order to manipulate it in correct way. In that respect, I always found git commands mostly intuitive.
Much later in my career I learnt that people were using git without even knowing anything about what a Merkle tree is and I must say I was extremely surprised. I'm not saying its good or bad, just describing my younger days.
DriftRegion
The article writes:
> they had not asked me to explain git, they had asked me to explain GitHub
This is often the case for me as well.
Hey, at least git owns it by calling the shell commands "porcelain" (with git itself being the plumbing -- https://stackoverflow.com/questions/6976473/what-does-the-te... ).
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.
SoftTalker
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.
Copy my changed files to a temporary directory.
Delete my working directory.
Checkout the latest version from the repo.
Copy my changed files back.
lukeschlather
The article says that git checkout confuses things that could be better accomplished with one of (git restore, git switch, git reset)
What you're doing sounds like git reset/git switch would be fine. I think I'm in favor of what the author suggests, conflating switch and reset/restore seems bad. It's going to take some effort to fix my habits though.
hmcdona1
Use `git stash` instead of copying files around manually to save yourself some time.
bluedevilzn
Parent comment is the quintessential example from the article that most people who know git didn't learn git properly.
SoftTalker
Yeah git rubbed me the wrong way from the beginning and I never learned it properly. My way makes the most sense to me. Stash? where? How do I get my files back? None of that is intuitive. I understand my way.
mschuster91
Now if git stash would support only stashing one specific file...
Izkata
git stash -- filename
fhars
The one bad point about checkout is that is one of the few git commands that can destroy data irretrievably, even without --force or -f or so. That is unexpected behaviour.
remram
What you want is 'git reset --mixed'
zzzeek
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 deprecate 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.
abuani
Conversely, it's an exceptional way of getting a highly engaging discussion. It's meant to elicit an emotional reaction and get people to read their article. I don't think they made any convincing arguments to actually deprecate the command, but highlights the complexity of a command that thousands of people issue on a daily basis without thinking about it.
zzzeek
> It's meant to elicit an emotional reaction and get people to read their article
I'll grant it for an article for wide readership but as a general tool of technical discourse used in places like github issues etc., highly inappropriate.
null
EE84M3i
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)
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.
dark-star
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.
Then again, until today I never knew about "git switch" so I, too, learned something today :)
ameliaquining
The problem is that it doesn't just change your working tree, it also (sometimes) changes HEAD. So the two behaviors both work very differently and are intended for very different use cases.
null
I'd rephrase and simplify this article a bit.
`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.
For more about the introduction of these commands and the details of the above see https://github.blog/open-source/git/highlights-from-git-2-23...