Back to all articles
technical-reference
🌳

Git Worktrees: Managing Multiple Working Directories

Stop juggling branches and stashing changes. Git worktrees let you run multiple checkouts simultaneously for parallel development, hotfixes, testing, and more.

January 11, 2026 6 min read
Share:
CW

Cody Williamson

Senior Software Engineer

Ever needed to work on a hotfix while in the middle of a feature? Or compare your current work against a different branch without stashing? Or run tests on an old commit while keeping your current work intact?

Git worktrees solve this. They let you check out multiple branches simultaneously in separate directories, all backed by the same repository. No cloning. No stashing. No branch switching that moves files around underneath your editor.

The Basic Idea

A worktree is a separate working directory linked to the same Git repository. You can have your main branch checked out in one directory, a feature branch in another, and a hotfix in a third—all at the same time.

Single command setup:

git worktree add -b feature-branch ../repo-feature

That does three things at once:

  • creates a branch
  • checks it out
  • puts it in a different directory

Now you’ve got two folders with the same repo, same history, but totally separate files on disk.

This is the part people trip over, so it’s worth saying plainly:

⚠️ Worktree Mental Model

Switching branches does not move you between folders. Each folder is its own checkout. You literally cd between them.

Why Use Worktrees

The main advantage is isolation without the overhead of cloning. Each worktree is completely independent:

  • Different branches checked out simultaneously
  • No stashing required when switching contexts
  • No waiting for Git to swap files around
  • IDE and build state stays intact per worktree

When you need to merge work from one worktree to another, it’s just normal Git operations:

cd ../repo-main
git switch main
git merge feature-branch

If you only want specific commits:

git cherry-pick <sha>

Everything happens locally. No pushing to temporary branches. No fetching from yourself.

Quick Experiments Without Branches

Another underrated trick is using worktrees without even creating a branch:

git worktree add ../repo-test <sha>

That gives you a detached HEAD checkout at a specific commit. Great for poking around, testing, or answering “what if” questions without any branch ceremony.

When you’re done:

git worktree remove ../repo-test

Directory gone. Metadata cleaned up. Life is good.

Cleanup and the Footgun Everyone Hits Once

If you delete the directory before telling Git about it, Git still thinks the worktree exists. That’s where this comes in:

git worktree prune

My usual flow:

git worktree list
git worktree prune

Mental model that helps:

  • remove = intentional cleanup
  • prune = garbage collection after you messed up

If you script or automate this stuff, this distinction matters.

✨ Scripting Tip

When automating worktree cleanup, always run git worktree prune as part of your teardown. It handles the case where directories get removed outside of Git’s control.

When Worktrees Are Great and When They’re Not

Worktrees shine when the problem is mostly:

  • I want multiple clean working directories
  • I don’t want extra clones
  • I don’t want to babysit refs

They’re less great if:

  • you explicitly want push/pull semantics
  • you want a hard boundary that behaves like a real remote
  • you’re coordinating across machines

In those cases, a bare repo or actual remote still makes sense.

Common Workflows

Here are practical patterns for using worktrees:

Emergency Hotfix

You’re deep in feature work when a production bug needs fixing:

# Create worktree for the hotfix
git worktree add -b hotfix-prod ../repo-hotfix main

# Fix the bug in ../repo-hotfix
cd ../repo-hotfix
# ... make changes ...
git commit -m "fix: critical bug"

# Merge to main and deploy
git switch main
git merge hotfix-prod

# Back to feature work without losing context
cd ../repo
# Your feature work is exactly as you left it

# Clean up when done
git worktree remove ../repo-hotfix
git branch -d hotfix-prod

Parallel Feature Development

Working on two features that touch the same files:

git worktree add -b feature-auth ../repo-auth
git worktree add -b feature-payments ../repo-payments

# Work on both simultaneously in separate editors
# Test each independently
# Merge them when ready without conflicts from switching

Code Review and Comparison

Need to review a PR or compare implementations:

# Check out the PR branch
git worktree add ../review-pr-123 pull/123/head

# Your main work stays untouched
# Compare files side-by-side in different directories
# Run their code without affecting your environment

# Remove when done reviewing
git worktree remove ../review-pr-123

Testing Against Different Versions

Run tests on multiple branches or commits simultaneously:

# Test current release
git worktree add ../test-v2.0 v2.0.0

# Test main branch
git worktree add ../test-main main

# Run tests in parallel
cd ../test-v2.0 && npm test &
cd ../test-main && npm test &

# Compare results

Historical Investigation

Need to check how something worked in the past:

# Check out a specific commit for investigation
git worktree add ../repo-old abc1234

# Poke around, test, understand the old behavior
# Your current work is untouched

# When done
git worktree remove ../repo-old

Experimental Refactoring

Try a risky refactor without committing to it:

# Create experimental worktree
git worktree add -b experiment-refactor ../repo-experiment

# Go wild with changes
# If it works, merge it
# If it doesn't, just delete the worktree

git worktree remove ../repo-experiment
git branch -D experiment-refactor

Automated Workflows

Perfect for CI/CD scripts or automation that needs clean checkouts:

# Create isolated worktree for build
git worktree add -b build-$(date +%s) ../build-dir

# Run build in isolation
cd ../build-dir
npm run build

# Copy artifacts and clean up
cp -r dist ../artifacts/
git worktree remove ../build-dir

Practical Considerations

A few things I’ve learned the hard way:

Disk space is real. Each worktree is a full checkout. If your repo is large, you’ll feel it. The .git directory is shared, but all the working files are duplicated.

Sparse checkouts help. If you only need specific paths in a worktree, you can combine this with sparse checkout to save space:

git worktree add --no-checkout ../repo-docs
cd ../repo-docs
git sparse-checkout init --cone
git sparse-checkout set docs/
git checkout main

Lock worktrees you want to keep. If you’ve got a worktree you want to prevent from being accidentally pruned:

git worktree lock ../repo-feature --reason "Long-running feature work"

To unlock it later:

git worktree unlock ../repo-feature

Closing Thought

Worktrees aren’t for every situation. Multiple clones still make sense sometimes, especially across machines or when you want complete isolation. But for local parallel development, hotfixes, code reviews, and experimentation, worktrees remove a lot of friction.

Once the mental model clicks—that worktrees are separate directories you cd between, not branches you switch—they become second nature. Give them a shot next time you find yourself stashing changes or cloning locally just to work on two things at once.

🎯 Worktree Essentials

  • âś“ Worktrees create separate working directories that share the same Git repository
  • âś“ Perfect for parallel development, hotfixes, and code reviews without cloning
  • âś“ Each worktree is a different directory - use cd, not git switch, to move between them
  • âś“ Use git worktree prune to clean up after manually deleted directories
  • âś“ Best for local work - use actual clones when you need complete isolation

Enjoyed this article? Share it with others!

Share:

Have a project in mind?

Whether you need full-stack development, cloud architecture consulting, or custom solutions—let's talk about how I can help bring your ideas to life.