Part IV: Chapter 4.3

git checkout / git switch

Moving HEAD Around

Switching branches does exactly two things: it rewrites .git/HEADto point at the new branch, then it updates your working directory to match that branch's commit tree. No magic — just a file write and a file sync.

Watch HEAD and the Working Directory

Click the buttons to switch branches. Watch both panels change in lockstep — the .git/HEAD file on the left, and the working directory on the right.

.git/HEAD

contentsref: refs/heads/main
resolves to commitc4d5e6f...
HEAD is a symbolic ref — it stores a branch name, not a hash

Working Directory

on branch main
index.html<h1>Home</h1>
style.cssbody { color: white; }
app.js// v1.0 stable

What Git Actually Does

When you run git switch feature, Git performs three steps in order:

  1. 1Resolve the branch name to its commit hash by reading .git/refs/heads/feature.
  2. 2Walk that commit's tree and update every file in the working directory to match. Files unique to the new branch appear; files that no longer exist are removed.
  3. 3Overwrite .git/HEAD with ref: refs/heads/feature.

checkout vs switch

git checkout is the old Swiss-army-knife command. It could switch branches, restore files, detach HEAD, and more — all with the same command. This was confusing.

Git 2.23 (2019) split it into two focused commands:

  • git switch <branch> — move HEAD to a branch
  • git switch -c <branch> — create and switch
  • git restore <file> — discard working directory changes

Both checkout and switch work today. Prefer switchin new scripts — it's clearer about intent.

When Git Refuses to Switch

Git will block a switch if you have uncommitted changes that would be overwritten by the new branch's tree. It is protecting you from losing work.

Terminal
$git switch feature
error: Your local changes to the following files would be overwritten by checkout:
style.css
Please commit your changes or stash them before you switch branches.
$# Option 1: commit first
$git add . && git commit -m 'wip'
$git switch feature
Switched to branch 'feature'
$# Option 2: stash and pop
$git stash
$git switch feature
$git stash pop