Git

What Is Git Checkout? Switch Branches Like a Pro

What Is Git Checkout? Switch Branches Like a Pro

Type git checkout and Git does one of two quite different jobs, depending on what comes next. Hand it a branch or a commit and it moves HEAD there, rewriting the working tree and index to match. Hand it a file and it restores that file.

Developers use it to switch branches and look at old releases, and also to throw away unstaged edits.

The manual page lists nine invocation forms under that one name, split into two modes (Git documentation, 2026).

The newer git switch and git restore commands each took over one of those modes. The original keeps working.

What is git checkout?

YouTube player

The command does two jobs. It moves HEAD to a branch or commit and updates the working tree and index to match, and it restores individual files from the index or from any commit.

Git’s manual splits these into a branch-switching mode, where git checkout branch-name points HEAD at that branch and rewrites the files in the working directory, and a file-restoring mode, where git checkout commit filename (or plain git checkout filename) replaces a file with an earlier version.

Git guesses whether the argument is a branch, a commit or a path. When a name is ambiguous, Git treats it as a branch or commit, and a double dash (git checkout -- file.txt) forces the path reading.

As in any version control system, a checkout selects which version of the project you are looking at.

That double duty is why Git 2.23, released on 16 August 2019, added git switch and git restore as dedicated replacements (Git documentation changelog). The older command still works in current releases.

What does git checkout change in the repository?

YouTube player

Depending on the form, the command rewrites where HEAD points, what the index holds, the file contents in the working tree, or some mix of those.

Why is GitHub the heart of open source?

Uncover GitHub statistics: developer community growth, repository trends, collaboration patterns, and the platform that powers modern software development.

Explore GitHub Data →
FormHEADIndexWorking tree
git checkout branchPoints to the branchMatches the branchMatches the branch
git checkout commitPoints to the commit (detached)Matches the commitMatches the commit
git checkout -- pathUnchangedUnchangedFile reset to index version
git checkout commit -- pathUnchangedFile updatedFile replaced

Pass a branch or commit and HEAD moves. Pass a path and it stays put.

The last row also touches the staging area. Git adds the restored file to the index, so it shows up as a staged change.

The blocking rule is narrower than most tutorials claim. A branch switch fails only when an uncommitted change touches a file that differs between your current commit and the target.

Every other uncommitted change comes along to the new branch.

Adding -m changes the failure case. Git saves the conflicting edits in a stash, switches, and reapplies them, and if reapplying conflicts, the entry stays in the stash list.

Looking to sharpen your Git skills? Branching, merging, rebasing, and everything else you need - including git rebase, git stash, and commit workflows - is on one page in the Git Cheat Sheet.

Nothing here contacts a remote. The command reads refs and objects already stored in the local repository.

How to switch, create and track branches with git checkout

YouTube player

Switching takes git checkout branch-name, and git checkout -b new-branch creates a branch and lands on it in one step. Name a branch that exists only on a remote and checkout builds a tracking branch instead.

Switching to an existing branch

git checkout feature-login sets the current branch to feature-login and updates the working directory to its contents.

  • git checkout - jumps back to the previous branch (Git reads the dash as shorthand for @{-1})
  • Running git checkout with no argument changes nothing and only prints tracking information for the current branch

Creating a new branch with -b

The -b flag starts the new branch at the current commit unless you name a start point.

Because a Git branch is only a pointer to a commit, the pointer costs almost nothing to create.

▶ GIT EXPLAINED

If you commit, branch, or merge code every day, it helps to know how Git came to be. This video covers how Linus Torvalds created Git in just 10 days after a license dispute and explains how its data model actually works.

Linus Torvalds Built Git in Days Out of Spite
Built in 10 Days Out of Spite. Git and its data model explained in plain language.

-b fails when the name is taken, while -B resets the existing branch to the start point instead.

For instance, git checkout -b hotfix-1.4 v1.4.0 starts the branch at the v1.4.0 tag.

Checking out a remote branch

YouTube player

git checkout downloads nothing, so the remote-tracking branch must already exist locally. Start by fetching from the remote to refresh that list.

  1. Run git fetch origin to update the remote-tracking branches
  2. Run git checkout feature-login, using the plain name without origin/
  3. Read the confirmation line, which reports that the new local branch tracks origin/feature-login

Git builds the local branch only when exactly one remote has a matching name, per the git-checkout reference. With two remotes carrying the same name, the command fails unless checkout.defaultRemote names a winner, for example origin.

The explicit form, git checkout --track origin/feature-login, skips the guessing. Pass --no-guess, or set checkout.guess, to turn the shortcut off.

How to check out a commit or a tag

Pass a commit hash or a tag name, such as git checkout a1b2c3d or git checkout v2.0, and HEAD points straight at that commit instead of a branch.

Find the commit hash with git log, which prints one per commit. A Git tag labels one commit by name, so it is the cleanest way to read the code of a release.

Checkout accepts a few kinds of target:

  • a full or abbreviated hash copied from git log
  • a tag name, as in git checkout v2.0
  • a relative ref, so git checkout main~2 reads the code two commits behind main
  • git checkout --detach main, which detaches at the tip of main without moving the branch

The Git manual frames this mode as inspection and throwaway experiments. It suits questions like when a bug first appeared.

Edits made in this state are safe to discard. Commits are another matter.

What is detached HEAD, and how are its commits recovered?

HEAD normally points at a branch name. In a detached state it points at a commit, so any new commit belongs to no branch.

The detached HEAD state is harmless for reading code. Trouble starts with the first commit.

The manual’s own example makes the risk concrete. Check out a tag, commit twice, then switch back to a branch, and those two commits have nothing pointing at them.

Garbage collection can delete unreferenced commits, and the reflog is the safety net with an expiry. Git drops reflog entries older than 90 days by default, and entries no longer reachable from the current tip after 30 days (git-gc documentation).

If you are still sitting on the detached commits, run git checkout -b rescue-branch. The commands git branch rescue-branch and git tag rescue-tag also keep the commits, but leave HEAD detached.

If you already left them behind, recover through the reflog:

  1. Run git reflog to list where HEAD pointed recently (git reflog -2 HEAD shows only the last two positions)
  2. Find the entry for your last detached commit and copy its hash
  3. Run git branch rescue-branch followed by that hash
  4. Check the result with git log rescue-branch

Past the expiry window, a gc run can remove the commits for good.

How to restore files with git checkout

Add a path to git checkout and it restores files instead of switching branches. Name no commit and the file comes from the index, name a commit and it comes from that commit.

  • git checkout -- src/app.js resets the file to its staged version, which discards your unstaged edits
  • After rm hello.c, running git checkout hello.c brings the file back from the index
  • git checkout main~2 Makefile swaps in the version from two commits back
  • git checkout -- '*.c' matches index entries, so deleted C files return too (keep the quotes so Git expands the glob, not the shell)

Check what will be lost with git diff before running any of these. Unstaged edits exist only in the working tree, so once a restore overwrites them, Git holds no copy to bring back.

Checkout also never deletes anything by default. In its default overlay mode it removes no files from the index or working tree, so restoring a directory from an old commit leaves files added since then in place (git-checkout manual).

To pick individual hunks, use git checkout -p. It walks through the differences and discards only the ones you accept. Unlike the plain path form, -p runs in no-overlay mode and has no overlay option.

A path with an unresolved merge conflict makes the restore fail until you stage it. --ours and --theirs pick one side, -m rebuilds the conflict markers, and -f skips unmerged files.

During git rebase and git pull --rebase the two labels swap, so --ours gives the branch you are rebasing onto and --theirs gives your own work. The surrounding workflow is covered in a guide to resolving merge conflicts in Git.

Which git checkout options matter?

A handful of options change behavior in ways worth knowing, and the table covers them.

OptionEffectExample
--track (-t)Sets upstream configuration, implies branch creation, names the local branch from the remote onegit checkout --track origin/hack
--no-trackSkips upstream setup even when branch.autoSetupMerge is truegit checkout --no-track -b scratch origin/main
--orphanStarts an unborn branch whose first commit has no parentgit checkout --orphan clean-history
-fSwitches regardless of local changes and untracked files in the waygit checkout -f main
-pInteractively discards the hunks you pickgit checkout -p -- src/app.js

With --track, origin/hack becomes a local branch named hack. If the remote name has no slash, or Git’s guess comes out empty, pass the name yourself with -b.

The manual gives --orphan one concrete use: publishing a clean tree without its full history, such as an open source release of a project whose past contains proprietary code.

The index and working tree stay as if you had checked out the start point. Run git rm -rf . right after if the new history should begin empty.

Be careful with -f. It discards uncommitted changes and any untracked files in the way, with no stash and no prompt, so it is the one option to type last and slowly.

Why does git checkout fail, and how is each error fixed?

YouTube player

Most failures trace back to one of two messages: “Your local changes to the following files would be overwritten by checkout” and “pathspec … did not match any file(s) known to git”.

The first one means Git found an uncommitted edit in a file that differs on the target, so it aborted before touching anything. A few fixes exist, and they are not equal.

FixKeeps your editsCost
CommitYesAdds a commit you may amend later
StashYesSits outside history, easy to forget
Discard the filesNoUnstaged work cannot be recovered
git checkout -fNoAlso removes untracked files in the way

Run git status first to see which files triggered the block.

Sources disagree on the wording. The manual’s example still shows “You have local changes to ‘frotz’; not switching branches”, while the text that current Git versions print in a terminal is the “would be overwritten by checkout” message.

The pathspec message means no branch, tag or commit carries that name, so Git read the argument as a file path. It says “file(s)” because the same command restores files.

  1. List local and remote-tracking names with git branch -a and compare the spelling
  2. If the branch is missing, run git fetch and retry
  3. If the hint says the name matched more than one remote tracking branch, run git checkout --track origin/name
  4. If you meant a file, confirm it is tracked, because checkout restores only paths Git knows about

Both errors abort before any file changes.

Is git checkout deprecated, and when to use git switch or git restore?

YouTube player

No. The git-checkout manual is still a full reference page. It was last revised in Git 2.55.0, dated 29 June 2026, and Git 2.56.0 (28 September 2026) left it unchanged.

The page points readers to git switch and git restore under SEE ALSO. The experimental label from the 2019 launch (GitHub Blog) does not appear in the current manual pages of either command.

Taskgit checkoutNewer command
Switch branchgit checkout featuregit switch feature
Create and switchgit checkout -b featuregit switch -c feature
Previous branchgit checkout -git switch -
Detach at a commitgit checkout --detach HEAD~3git switch --detach HEAD~3
Start an unborn branchgit checkout --orphan docsgit switch --orphan docs
Discard unstaged editsgit checkout -- app.jsgit restore app.js
File from another commitgit checkout main~2 Makefilegit restore --source main~2 Makefile

Everyday branch switching in Git is what git switch was built for. The mapping is not one to one, though.

  • git switch -c leaves the branch uncreated and unreset when the switch fails
  • git switch --orphan removes all tracked files, while git checkout --orphan keeps the index and working tree as the start point had them
  • git restore defaults to no-overlay and deletes tracked files absent from the source, where checkout path restores remove nothing

The manual also ties the two worlds together. git restore --staged hello.c does for one path what git reset does, and git restore --source=HEAD --staged --worktree hello.c matches the checkout path form.

Switch and restore make sense on Git 2.23 or newer, and especially when a mistyped argument must never be read as a file path (the manual’s own example is a branch named hello.c).

Keep git checkout on machines running a Git older than 2.23, in scripts and CI jobs that already work, and on teams with muscle memory and no reason to retrain it.

Rewriting working scripts buys nothing, since the manual still documents every form. New habits are another matter.

git checkout FAQ

Is git checkout the same as svn checkout?

Not at all. Subversion’s checkout downloads a working copy from a central server. Git’s version never downloads anything and only moves between versions already stored in the local repository.

How is git checkout different from git clone?

git clone copies an entire repository from a remote and checks out its default branch. Cloning runs once per machine, while checkout runs constantly inside a repository that already exists.

Does git checkout work like git reset?

Not really. Checkout moves HEAD and leaves branches where they are, while reset moves the current branch itself to another commit. Reset can also rewrite the index and working tree, so the two commands change different things.

Does it matter whether I check out main or master?

Only the name must match. git checkout accepts whichever branch name the repository uses and has no preference between them.

Run git branch to see the exact name, since a repository created years ago often says master where a new one says main.

Can I check out a branch that another worktree already has open?

Not unless you pass –ignore-other-worktrees. A git worktree gives each branch its own working directory, which removes the need to switch at all.

Protecting Uncommitted Work Before You Switch

YouTube player

Uncommitted work survives a git checkout only when it is saved first, and the safe order runs from reversible actions to irreversible ones.

  • Run git status to see what is at risk
  • Commit or stash everything worth keeping
  • Discard or force only what is disposable

Commit and stash can be undone later, while a discard or -f cannot, so they always come first.

The price is one extra commit or stash per switch, a few seconds against unstaged edits Git cannot bring back.

The order flips only when the edits are disposable, such as generated build files, where -f is the faster path.

A one-page cheat sheet for Git covers the commands that sit next to checkout.

Bogdan Sandu

Stay sharp. Ship better code.

Every week: one curated article, one tool worth knowing, one tip you can use tomorrow. No noise, no padding.