Git Checkout

git checkout switches between branches and updates the files in your working directory to match the version stored in a specific branch or commit. It’s one of Git’s oldest commands — and one of its most overloaded, which is exactly why newer Git split part of its job out into two other commands. This is the eighth post in this site’s Git command guide, following Git Branch.

Basic Usage

Suppose you’re on a branch called feature-branch and want to switch to main:

$ git checkout main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.

You can also check out a specific commit by its hash, putting you in a detached HEAD state — useful for inspecting old code without affecting any branch:

$ git checkout 87a3cde
Note: switching to '87a3cde'.

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.

HEAD is now at 87a3cde Fix bug in login feature

That “detached HEAD” warning is Git telling you that any commits you make here won’t belong to a branch — if you check out a branch afterward without saving your work, those commits become unreachable and eventually get garbage collected.

checkout vs switch vs restore

Historically, git checkout did two unrelated jobs: switching which branch you’re on, and discarding working-directory changes to a file. Cramming both into one command meant a typo could either move you to a different branch or silently throw away uncommitted work, depending on the argument. Git 2.23 (August 2019) introduced git switch and git restore to split those responsibilities into commands that can’t be confused for each other. checkout still exists and still works exactly as before — it hasn’t been deprecated — because it’s baked into years of scripts, CI configs, and documentation.

CommandPurposeExample
git checkoutSwitches branches OR discards file changes, depending on arguments (legacy, overloaded)git checkout main
git switchSwitches branches only — nothing elsegit switch main
git restoreDiscards or restores file changes only — never touches branchesgit restore index.html

The equivalents of the two checkout examples above, using the newer commands:

$ git switch main
$ git restore index.html

I still type checkout out of muscle memory more often than not, and there’s nothing wrong with that — but if you’re writing a script or teaching someone new, switch/restore are clearer about intent and harder to misuse.

How the Code Works

  • git checkout <branch> moves HEAD to point at that branch and updates every tracked file in your working directory to match it.
  • git checkout <commit-hash> does the same thing but lands you on a specific commit instead of a branch tip, in detached HEAD state.
  • git checkout -b <new-branch> creates a new branch from your current position and switches onto it in one step.
  • Checking out a branch with uncommitted changes that conflict with the target branch will be blocked by Git rather than silently overwritten.

FAQs

Is git checkout deprecated now that switch and restore exist?

No. checkout is fully supported and isn’t going away — switch and restore were added as clearer, narrower alternatives, not replacements that obsolete the original.

What does “detached HEAD” actually mean?

It means HEAD points directly at a commit instead of at a branch. You can still make commits, but they won’t be part of any branch’s history unless you create one from that point with git switch -c new-branch-name before moving away.

How do I discard local changes to a single file?

Use git restore <file> (Git 2.23+) or the older equivalent git checkout -- <file>. Both throw away uncommitted changes to that file, restoring it to its last committed state.

See Also: This Site’s Git Command Guide

This post is part of a 13-part Git command guide on this site:

Conclusion

I don’t think checkout needs to be retired from your vocabulary — it’s still everywhere in real codebases and Stack Overflow answers from the last decade. What’s worth internalizing is just the split: when you mean “go to a different branch,” reach for switch; when you mean “undo my local edits,” reach for restore. With your branch sorted, the next step in the workflow is sending your commits somewhere, covered in Git Push.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.