git checkout switches branches, restores files from history, or creates a new branch—depending on the arguments you pass. Most day-to-day confusion comes from mixing up branch switches with file restores, especially after Git 2.23 introduced git switch and git restore as clearer commands.
What git checkout does today
At its core, checkout moves HEAD (your current commit pointer) and updates the working tree to match. Common forms:
# Move to an existing branch
git checkout main
# Create and move to a new branch
git checkout -b feature/login
# Restore a single file from another commit or branch
git checkout main -- src/app/page.tsx
# Detached HEAD: point at a specific commit (read-only exploration)
git checkout abc1234
Modern Git documentation encourages git switch for branches and git restore for files, but git checkout remains widely used in scripts and older tutorials.
Branch checkout step by step
When you run git checkout feature-x on a clean working tree:
- Git verifies the branch exists locally (or tries remote tracking rules if configured).
- HEAD moves to the branch tip commit.
- Files in your working directory update to match that commit.
If you have uncommitted changes, Git may refuse the switch to prevent overwriting work, or it may carry changes forward if there is no conflict. That behavior surprises people who expect a hard reset.
Safer habit before switching: git status. Commit, stash, or discard intentional work first.
Creating branches with -b
git checkout -b fix/typo origin/main
This creates fix/typo starting from origin/main and checks it out. Equivalent modern form:
git switch -c fix/typo origin/main
Use descriptive branch names tied to tickets or tasks—future you will search history by branch name.
Checking out files (the easy way to lose work)
git checkout HEAD -- path/to/file
This replaces the file in your working tree with the version from HEAD (last commit). It is useful when you want to undo local edits to one file without touching others.
To pull a file from another branch without switching branches:
git checkout other-branch -- path/to/file
That stages the file as a change on your current branch. Review with git diff --cached before committing—you may have just copied unexpected content.
Detached HEAD state
Checking out a commit hash puts you in detached HEAD:
git checkout v1.2.0
You can look around and run tests, but new commits are not on a named branch until you create one:
git switch -c investigate-regression
If you commit in detached HEAD and switch away without creating a branch, Git may eventually garbage-collect those commits. Always branch if you mean to keep work.
Checkout vs reset vs restore
| Goal | Prefer |
|---|---|
| Change branch | git switch <branch> or git checkout <branch> |
| Discard unstaged edits in a file | git restore <file> |
| Unstage a file | git restore --staged <file> |
| Move branch pointer backward (destructive) | git reset (understand hard/mixed/soft) |
git checkout . (restore entire tree from index) is a footgun on large repos. Prefer explicit paths or git restore . after confirming status.
Remote branches
First time checking out a remote branch:
git fetch origin
git checkout feature/login
If Git knows about origin/feature/login, it often creates a local tracking branch automatically. If not:
git checkout -b feature/login origin/feature/login
Common errors and fixes
“Your local changes would be overwritten by checkout”
Stash: git stash push -m "wip" → checkout → git stash pop. Or commit WIP on a throwaway branch.
“pathspec did not match any file(s)”
Typo in path or file not present in the target tree. Tab-complete paths; use git ls-tree -r HEAD --name-only | grep partial.
Detached HEAD after fetching tags
Normal for tag builds. Create a branch if you need to patch the tag snapshot.
Scripts and CI
CI systems usually git checkout a ref in shallow clones:
git checkout "$GITHUB_SHA"
Locally, prefer explicit refs in automation (git checkout main) instead of ambiguous names. Avoid checkout in deploy scripts without set -e—failed checkouts have caused production deploys from wrong trees.
FAQ
Should I learn switch and restore instead? Yes, if you are new—they split checkout into clearer verbs. Legacy checkout remains valid.
Does checkout pull from remote? No. Fetch first (git fetch), then checkout the updated branch.
Can checkout merge? No. Merging is git merge or pull with merge/rebase strategies.
What about git checkout --track? Sets upstream tracking when creating a local branch from a remote; git switch -c name --track origin/name is the modern equivalent.
Mastering checkout means knowing whether you are moving HEAD, restoring files, or exploring history—and pausing when git status is not clean. That single habit prevents most “where did my changes go?” incidents.
How checkout interacts with merge and rebase
Before merging or rebasing, you must be on the branch that should receive commits:
git switch main
git merge feature/login
If you checkout a file from another branch mid-merge, you can accidentally mix conflict resolutions. During conflicts, use git status to see unmerged paths; resolve, git add, then continue merge or rebase.
git rebase replays commits onto a new base—checkout is involved internally, but you normally drive rebase with git rebase main, not manual checkouts.
Sparse checkouts and partial clones
Monorepos sometimes use sparse checkout to limit working tree size. Checkout behavior still applies to visible paths; hidden paths may not exist locally until you expand sparse patterns. Consult git sparse-checkout docs before scripting checkout in huge repositories.
Hooks and checkout
Some teams install post-checkout hooks to reinstall dependencies when package-lock.json changes. If checkout feels slow, check .git/hooks and CI templates—hooks run on every branch switch.
Recovering from mistakes
Checked out wrong branch and committed — Create a branch at the current commit to preserve work: git branch rescue, then move commits with cherry-pick or reset as needed.
Lost commits after detached HEAD — Use git reflog to find the commit hash, then git switch -c recovered-branch <hash>.
Restored file unintentionally — If the old version still exists in reflog or another branch, checkout from there again; otherwise recover from remote or backups.
Comparison with git worktree
git worktree add lets multiple branches exist in separate directories simultaneously—useful when you must hotfix production while a feature branch stays checked out elsewhere. Checkout still applies within each worktree; you cannot checkout the same branch in two worktrees by default.
Team conventions worth documenting
Document in your CONTRIBUTING.md:
- Default branch name (
mainvsmaster) - Whether feature branches are rebased or merged
- If force-push is allowed on shared branches (usually no)
- Required status checks before merge
New contributors who only know git checkout from tutorials will thank you for explicit git switch examples alongside legacy commands.
FAQ (extended)
Does checkout update submodules? Only if configured; submodule paths may need git submodule update after branch switches.
Can I checkout a folder? Git checks out tree objects, not arbitrary folders without pathspecs—use pathspecs or sparse checkout.
What about git checkout @{-1}? Checks out the previous branch—a quick undo for branch switches if your shell history is intact.
GUI clients — Desktop apps call the same operations; understanding CLI checkout clarifies what the GUI is doing under the hood.
Further Reading
Discover more articles on similar topics across our network

Comments
Loading comments…