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:
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 cleanupprune= garbage collection after you messed up
If you script or automate this stuff, this distinction matters.
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!