git checkout: one command with three jobs
Updated July 31, 2026
git checkout does three different things: it moves you between branches, pulls files out of a commit, and parks you on a commit with no branch attached. One name over three unrelated jobs, which is where the confusion comes from.
Git 2.23 (2019) split those jobs into two commands with clear names: git switch walks between branches, git restore brings files back. checkout itself stayed, works exactly as it did, and is not going away. But forum answers, older articles and in-house instructions are all written with it, so you will be reading it for a long time yet.
Job one: branches
$ git checkout feature-x
Switched to branch 'feature-x'
$ git checkout -b feature-x
Switched to a new branch 'feature-x'Today the same thing is written git switch feature-x and git switch -c feature-x. The output is identical; only the command name differs.
Job two: files
git checkout -- report.txt puts the file back to the way it looks in the index (staging area); if you staged nothing, that is the way it looked in the last commit. git checkout HEAD~1 -- report.txt takes the version from the commit before that and stages it as well. The modern spelling is git restore report.txt and git restore --source=HEAD~1 report.txt, and the second one touches the file only, leaving the index alone.
Slow down here. This is the dangerous form:
$ git checkout -- report.txt
$ git status
On branch main
nothing to commit, working tree cleanNo question, no list of what went away. Edits git never saw have nowhere to come back from: they are not in a commit, not in the index, not in git stash. A look at git diff before that command pays for itself.
Job three: a commit with no branch
$ git checkout 610d731
Note: switching to '610d731'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.This is detached HEAD: HEAD points straight at a commit, skipping the branch name. The explicit modern spelling is git switch --detach 610d731, and git switch - takes you back.
Common mistakes
A branch name and a file name are easy to mix up. If the repository holds both a branch called report.txt and a file called report.txt, then git checkout report.txt quietly switches the branch and leaves the file alone. Two dashes settle the argument: anything after -- is treated as a file name.
A file that never made it into a commit has nothing to be restored from: error: pathspec 'notes.txt' did not match any file(s) known to git. Check the spelling, and check that the file ever reached the history at all.