Skip to content
masterclass Buddy

Git · Command

git checkout

git checkout either moves you to another branch or commit, or overwrites chosen files with the version stored in the index or in a given commit. It is the older all-in-one command whose two jobs are now also covered separately by git switch and git restore.

Last updated

How it works

Git looks at the arguments to decide which job to do. Given a branch name and no paths, it points HEAD at that branch and updates the index and working tree to match. Uncommitted edits come along unless the switch would overwrite them. Given a commit that is not a branch, HEAD points straight at that commit, which is called a detached HEAD. Given pathspecs, HEAD stays where it is. Git copies those files from the index, or from a tree-ish if you name one. With a tree-ish, the restored files are also staged. If an argument could be either a ref or a file, Git treats it as a ref unless you put -- in front of the paths.

Syntax

git checkout [-q] [-f] [-m] [[-b|-B|--orphan] <new-branch>] [<start-point>]
git checkout [-q] [-f] [-m] [--detach] <commit>
git checkout <tree-ish> [--] <pathspec>...
git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [--] <pathspec>...
git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>...]

Parameters

NameTypeDescription
<branch>refThe branch to switch to. If the name is not a local branch but is a valid commit, HEAD becomes detached. @{-N} and - (the previous checkout) are accepted.
<new-branch>stringName of the branch created by -b, -B or --orphan.
<start-point>commitThe commit a new branch starts from. Defaults to HEAD. A...B means their merge base.
<tree-ish>commit/treeWhere file contents are taken from when paths are given. If omitted, the index is used.
<pathspec>...pathspecLimits the operation to these files or directories.
-b / -BflagCreate a branch and switch to it. -B resets the branch if it already exists.
--detachflagCheck out a commit with HEAD detached, even when you give a branch name.
-f / --forceflagThrow away local changes when switching. When restoring paths, skip unmerged entries instead of failing.
-m / --mergeflagCarry conflicting local changes across the switch by stashing and reapplying them. When restoring paths, recreate the conflicted merge result.
--ours / --theirsflagFor unmerged paths, take stage #2 (ours) or stage #3 (theirs) from the index.
-p / --patchflagChoose hunks interactively and revert them in the working tree.
--orphanflagCreate an unborn branch whose first commit will have no parent.

Key points

  • -B works like -b, but if the branch already exists it moves that branch to the start point instead of stopping with an error.
  • --detach, or naming a commit that is not a branch, gives you a commit to look at or experiment with without moving any branch.
  • Use @{-N} for the Nth branch or commit you checked out before. A plain - means the previous one, so 'git checkout -' switches back.
  • If the branch name only exists as a remote-tracking branch on exactly one remote, Git creates a local branch that tracks it. --no-guess turns this off, and checkout.defaultRemote decides which remote wins when several match.
  • Git normally refuses to switch if your edits would be overwritten. With -m, it stashes the conflicting edits, switches, and then reapplies them.
  • When you name a commit and paths, the files are staged as well as written to the working tree, not just written to disk.
  • --orphan starts a branch with a separate history. Its first commit has no parent, which helps when publishing a tree without its old history.
  • -p shows the differences hunk by hunk so you can pick which edits to throw away, using the same interface as git add -p.

Common mistakes

  • Commits made on a detached HEAD are lost once you switch away, unless a branch or tag points to them. If that happens, find them with git reflog.
  • If a file has the same name as a branch, Git treats the argument as the branch. Put -- before file names so they are read as paths.
  • During a rebase, --ours and --theirs seem reversed: --ours is the branch you are rebasing onto, and --theirs is your own work.
  • -f does not keep your work safe. It throws away local edits and any untracked files that are in the way.

Example: Branching, restoring files and leaving a detached HEAD

#!/usr/bin/env bash
set -e

# Create a feature branch from main and switch to it
git checkout -b feature/login main

# Throw away unstaged edits to one file (restore it from the index)
git checkout -- src/app.js

# Take a file from two commits back on main (it is staged too)
git checkout main~2 -- Makefile

# Look at an old release without moving any branch
git checkout --detach v2.0

# Keep experimental work made there by putting it on a new branch
git checkout -b spike/v2-fix

# Go back to the branch you were on before
git checkout feature/login

The script runs through the common checkout jobs: creating a branch, restoring files from the index or from a commit, detaching HEAD, saving work made while detached, and switching back with a branch name.

When to use it

Starting a topic branch

Create a branch from main or a remote branch with 'git checkout -b feat origin/main' and start working on it right away.

Undoing a bad edit to one file

Restore a file from the index, or pull the version from an earlier commit after a broken change.

Inspecting an old release

Check out a tag with HEAD detached to reproduce a bug, then make a branch only if you need to keep fixes.

Resolving merge conflicts per file

Use --ours or --theirs on conflicted paths to keep one side in full, or -m to bring the conflict markers back.

Interview questions

QWhat is a detached HEAD, and how do you end up in one with git checkout?

Normally HEAD points to a branch name. With a detached HEAD it points straight at a commit. This happens when you check out a tag, a commit hash or an expression like master^^, or when you use --detach. New commits made in this state are referenced only by HEAD.

Follow-up: You already switched away and the detached commits seem gone. How do you get them back? Find their IDs with git reflog (or git log -g), then create a branch or tag on them before garbage collection removes them.

QWhat is the difference between 'git checkout file.txt' and 'git checkout HEAD file.txt'?

Without a tree-ish, the file is copied from the index into the working tree, so only unstaged edits are thrown away. With HEAD (or any commit), the file is replaced with the committed version in both the index and the working tree, which also drops staged changes.

Follow-up: How do you get the same result with the newer commands? 'git restore file.txt' restores from the index, and 'git restore --source=HEAD --staged --worktree file.txt' matches the HEAD form.

QYour edits block a branch switch with 'You have local changes; not switching branches'. What are your options with checkout?

Use 'git checkout -m <branch>' to stash the conflicting edits, switch, and reapply them. Use -f to switch and throw the edits away. You can also commit or stash the edits yourself first.

Follow-up: What happens if reapplying with -m causes conflicts? The stash entry is kept. Resolve the conflicts and run git stash drop, or run git reset --hard and apply the changes later with git stash pop.

  • git switch
  • git restore
  • git branch
  • git reflog
  • git stash
  • git worktree
  • git reset
  • git add

Source: Git - git-checkout Documentation. Checked 2026-11-02.