Skip to content

Git Worktree: The Feature That Eliminated My Context-Switching Overhead

Why I stopped stashing, stopped branch-juggling, and started working on multiple branches simultaneously.


The Context-Switching Tax

I was deep in a complex refactoring on a feature branch — files changed across a dozen modules, a delicate state I'd spent hours building. Then Slack: "Critical bug in production, can you look?" My options were terrible: stash everything (hoping the stash would apply cleanly later), commit half-done work (polluting history), or clone the repo again (waiting for a fresh build). Every option cost me 15-30 minutes of context rebuilding.

Then I discovered git worktree. It changed how I think about branches entirely.

What Is a Worktree?

A git worktree is an additional working directory linked to the same repository. Each worktree has its own checked-out branch, its own index, and its own working files — but they share the same .git object database. No duplication of history, no separate clone, no extra fetch.

# Create a new worktree for a hotfix, checked out from main
git worktree add ../project-hotfix main

# Or create a worktree with a new branch
git worktree add ../project-experiment -b experiment/new-cache

Now I have two directories: - project/ — my feature branch, untouched - project-hotfix/ — clean main branch, ready for the fix

I switch directories instead of switching branches. My feature work stays exactly as I left it.

My Worktree Layout

Over time, I settled on a consistent directory structure:

~/dev/
  laas-main/          # Always on main, for quick lookups
  laas-feature/       # Current feature work
  laas-hotfix/        # Emergency fixes (created on demand)
  laas-review/        # Checking out PRs for code review
# My setup script for a new project
git clone git@github.com:org/project.git project-main
cd project-main
git worktree add ../project-feature -b feature/current-work
git worktree add ../project-review main

Daily Workflow With Worktrees

Morning: Start feature work

I cd into my feature worktree and pick up where I left off. No stash-pop, no checkout, no waiting. The files are exactly as I left them, IDE state preserved.

Interruption: Production issue

# Create a hotfix worktree from latest main
cd ~/dev/project-main
git pull
git worktree add ../project-hotfix -b hotfix/fix-timeout

# Work on the fix in the hotfix directory
cd ../project-hotfix
# ... fix, test, push ...

# When done, remove the worktree
cd ../project-main
git worktree remove ../project-hotfix

Code review: Check out a PR

cd ~/dev/project-review
git fetch origin pull/123/head:pr-123
git checkout pr-123
# Run tests, inspect code, leave comments

My feature work was never touched. Zero context loss.

Worktrees and Build Systems

One subtlety: each worktree has its own working directory, so build artifacts are independent. This is actually a feature — I can have the main branch compiled and running while building a feature branch separately. No artifact contamination.

For projects with expensive builds, I keep a main worktree always built, so I can instantly compare behavior:

# In main worktree: always up-to-date, always built
cd ~/dev/project-main
git pull && make build

# In feature worktree: my current work
cd ~/dev/project-feature
make build && make test

# Quick comparison if something seems wrong
diff <(cd ~/dev/project-main && ./cli --version) \
     <(cd ~/dev/project-feature && ./cli --version)

Managing Worktrees

Keeping track of worktrees is simple:

# List all worktrees
git worktree list
# /home/user/dev/project-main     a1b2c3d [main]
# /home/user/dev/project-feature  d4e5f6g [feature/auth]
# /home/user/dev/project-review   h7i8j9k [pr-123]

# Remove a worktree (when you're done with it)
git worktree remove ../project-hotfix

# Prune stale worktree references (if directory was deleted manually)
git worktree prune

Important constraint: each branch can only be checked out in one worktree at a time. If main is checked out in project-main/, you can't also check it out in project-review/. This prevents conflicting modifications to the same branch.

Worktrees vs. Multiple Clones

Before worktrees, I sometimes used multiple clones. Here's why worktrees are better:

Aspect Multiple Clones Worktrees
Disk space Full copy of objects per clone Shared objects
Fetch Fetch in each clone separately Fetch once, all worktrees see it
Branch sync Manually pull in each Shared refs
Setup time Clone + configure each One command
Independence Complete isolation Share same .git

The only case where I still use a separate clone is when I need a different git configuration (different user identity for a fork, for example).

Key Takeaway

Worktrees eliminate the false choice between "switch context now" and "lose my current state." They make branch-based workflows truly parallel instead of sequential. Once I started using them, stashing and work-in-progress commits became rare. Each task gets its own directory, its own branch, and my attention — without destroying what came before.


Tags: git, worktree, productivity, context-switching, workflow

Reference