# Main feature branch
~/project/main/
# Hotfix in separate directory
~/project/hotfix-auth/
# Code review in another
~/project/review-pr-42/You are deep in a feature branch. Dozens of uncommitted changes. Your coworker asks you to review their PR. Or worse, production breaks and you need to push a hotfix immediately.
The typical workflow: stash everything, switch branches, do the work, switch back, pop the stash, hope nothing conflicts. Repeat this five times a day and you start to hate git.
Git worktrees solve this problem completely. Instead of switching branches, you check out multiple branches in separate directories. Each directory is a fully functional working copy of your repository. No stashing. No context switching. No conflicts.
#What Are Worktrees?
A worktree is an additional working directory linked to your repository. Your main repository stays where it is. Each worktree lives in its own folder with its own branch checked out.
~/projects/myapp/ # Main repo, on 'feature/dashboard'
~/projects/myapp-hotfix/ # Worktree, on 'hotfix/auth-bug'
~/projects/myapp-review/ # Worktree, on 'pr/42-new-api'
All three directories share the same git history. Commits made in any worktree are visible to all others. But each has its own working directory, its own staged changes, and its own HEAD.
This is fundamentally different from cloning the repo multiple times. Clones are independent copies with separate histories. Worktrees are linked views into the same repository. Push from any worktree and the others see it immediately.
#Creating Your First Worktree
The basic command creates a new worktree directory with a branch checked out.
# Create a worktree for an existing branch
git worktree add ../myapp-hotfix hotfix/auth-bug
# Create a worktree with a new branch
git worktree add ../myapp-experiment -b experiment/new-feature
# Create a worktree from a specific commit
git worktree add ../myapp-v2 v2.0.0The first argument is the path where the worktree will be created. The second is the branch or commit to check out. If you add the -b flag, git creates a new branch.
A common pattern is to keep worktrees as sibling directories to your main repo.
# You're in ~/projects/myapp
cd ~/projects
git worktree add ./myapp-hotfix hotfix/auth-bug
git worktree add ./myapp-review origin/feature/new-apiNow you have three directories that are all the same repository.
#Common Worktree Patterns
#Hotfixes Without Disruption
Production breaks. You need to fix it now. But your main repo is mid-feature with a broken build.
# From your main repo
git worktree add ../myapp-hotfix main
# Navigate to the hotfix worktree
cd ../myapp-hotfix
# Create and push the fix
git checkout -b hotfix/critical-bug
# ... make your fix ...
git commit -m "Fix critical auth bypass"
git push origin hotfix/critical-bugYour feature branch stays exactly as you left it. When the hotfix is merged, delete the worktree and continue working.
#Code Reviews Without Context Loss
Someone asks you to review their PR. Instead of switching branches and losing your mental model of your current work, create a worktree.
# Fetch the PR branch
git fetch origin pull/42/head:pr-42
# Create a worktree for the review
git worktree add ../myapp-review pr-42
# Open it in a new VS Code window
code ../myapp-reviewReview the code, run tests, leave comments. When you are done, remove the worktree. Your main work never moved.
#Testing Against Main
You want to verify your feature works when merged to main. But you do not want to actually merge yet.
# Create a worktree on main
git worktree add ../myapp-test-main main
cd ../myapp-test-main
# Merge your feature locally
git merge origin/feature/my-feature
# Run tests
npm test
# If it works, great. If not, you know before the PR.
# Either way, just delete the worktree.This is safer than merging main into your feature branch, which pollutes your branch history.
#Worktrees and Claude Code: The Ultimate Parallel Workflow
I wrote previously about running multiple Claude Code terminals simultaneously. Worktrees take this pattern to another level.
The core insight: when you run multiple Claude instances in the same repository, they can conflict. If Terminal 1 modifies UserService.ts while Terminal 2 also tries to edit it, one will overwrite the other. You have to carefully divide work by file boundaries.
With worktrees, this limitation disappears. Each Claude instance operates in a completely separate directory. There is no possibility of file conflicts because they are literally different file systems.
#The Setup
Create worktrees for different work streams.
# Main repo for your primary feature
~/projects/myapp/
# Worktree for a hotfix
git worktree add ../myapp-hotfix hotfix/auth-bug
# Worktree for a second feature
git worktree add ../myapp-feature-b feature/notificationsOpen each in a separate VS Code window. Each window has its own integrated terminal. Each terminal runs its own Claude Code instance.
┌─────────────────────────────────────────────────────────────┐
│ VS Code Window 1: ~/projects/myapp/ │
│ Branch: feature/dashboard │
│ Terminal: claude "Build the analytics dashboard" │
├─────────────────────────────────────────────────────────────┤
│ VS Code Window 2: ~/projects/myapp-hotfix/ │
│ Branch: hotfix/auth-bug │
│ Terminal: claude "Fix the JWT validation issue" │
├─────────────────────────────────────────────────────────────┤
│ VS Code Window 3: ~/projects/myapp-feature-b/ │
│ Branch: feature/notifications │
│ Terminal: claude "Implement push notification service" │
└─────────────────────────────────────────────────────────────┘
Three Claudes working on three separate branches. No file conflicts possible. Each maintains its own conversation context focused on its specific task.
#When Worktrees Beat Multi-Terminal
The multi-terminal approach I described previously works great when all work is on the same branch. One terminal builds components, another writes tests, a third handles the API. They divide work by file type.
Worktrees are better when:
- You are working on genuinely separate branches
- The work streams might touch the same files
- You need complete isolation between tasks
- You want separate VS Code windows with separate file explorers
Multi-terminal is better when:
- All work is for the same feature
- You want everything in one VS Code window
- You are coordinating closely related tasks
- You need to see changes across terminals in real time
In practice, I use both. Multi-terminal within a single worktree for feature work. Separate worktrees when handling interrupts like hotfixes or code reviews.
#VS Code Multi-Root Workspaces
If you prefer a single VS Code window, you can add multiple worktrees as workspace folders.
# Create a workspace file
cat > ~/projects/myapp.code-workspace << 'EOF'
{
"folders": [
{ "path": "myapp", "name": "Feature: Dashboard" },
{ "path": "myapp-hotfix", "name": "Hotfix: Auth" },
{ "path": "myapp-review", "name": "Review: PR 42" }
],
"settings": {
"files.exclude": {
"**/.git": true
}
}
}
EOF
# Open the workspace
code ~/projects/myapp.code-workspaceNow you have one VS Code window with all three worktrees visible in the file explorer. Each folder shows its branch name. You can have terminals open in each folder running separate Claude instances.
#Managing Worktrees
#List All Worktrees
git worktree list
# Output:
# /Users/you/projects/myapp abc1234 [feature/dashboard]
# /Users/you/projects/myapp-hotfix def5678 [hotfix/auth-bug]
# /Users/you/projects/myapp-review ghi9012 [pr-42]This shows the path, the current commit, and the branch for each worktree.
#Remove a Worktree
When you are done with a worktree, remove it properly.
# Remove the worktree (keeps the branch)
git worktree remove ../myapp-hotfix
# Force remove if there are uncommitted changes
git worktree remove --force ../myapp-hotfixIf you manually delete a worktree directory without using git worktree remove, git will complain. Clean up with:
git worktree pruneThis removes references to worktrees whose directories no longer exist.
#Lock a Worktree
If a worktree is on external storage that might disconnect, lock it to prevent accidental removal.
git worktree lock ../myapp-external --reason "On USB drive"
git worktree unlock ../myapp-external#Best Practices
#Directory Naming
Use a consistent naming scheme. I prefer the main repo as the bare name and worktrees with suffixes.
myapp/ # Main repo
myapp-hotfix/ # Short-lived hotfix
myapp-review-42/ # PR review with number
myapp-experiment/ # Experimental work
This keeps them sorted together in file listings and makes the purpose clear.
#Keep Worktrees Short-Lived
Worktrees work best for temporary work. The longer a worktree lives, the more likely it drifts from main and causes confusion.
Good uses:
- Hotfixes that ship in hours
- Code reviews that take a day
- Testing merge conflicts before opening a PR
- Parallel work on two features when one is nearly done
Bad uses:
- Long running features that take weeks
- Permanent development environments
- Backup copies of your repo
For long running work, consider just having multiple repos or using branch switching with proper stashing practices.
#Avoid Checking Out the Same Branch
Git does not allow two worktrees to have the same branch checked out. This prevents confusion about which working directory has the "real" state of a branch.
# This fails if main is already checked out elsewhere
git worktree add ../myapp-test main
# error: 'main' is already checked out at '/Users/you/projects/myapp'If you need to test against main while main is checked out in your main repo, check out the commit directly.
# Checkout the commit, not the branch (detached HEAD)
git worktree add ../myapp-test $(git rev-parse main)#Clean Up Regularly
Abandoned worktrees clutter your disk and your git state. Run git worktree list periodically and remove worktrees you no longer need.
# List worktrees
git worktree list
# Remove ones you're done with
git worktree remove ../myapp-old-experiment
# Clean up any orphaned references
git worktree prune#When to Use Worktrees vs Just Switching Branches
| Scenario | Use Worktrees | Use Branch Switching |
|---|---|---|
| Quick hotfix while mid-feature | Yes | No |
| Code review that needs running locally | Yes | Maybe |
| Parallel work on two features | Yes | No |
| Feature branch for a few hours | No | Yes |
| Testing before merging | Yes | No |
| Daily development on one feature | No | Yes |
| AI coding with multiple Claude instances | Yes | Maybe |
Worktrees add complexity. They are worth it when context switching is expensive or when you need true isolation. They are overkill for simple branch switches on clean working directories.
#Summary
Git worktrees let you work on multiple branches simultaneously without stashing or losing context. Each worktree is a separate directory with its own checked-out branch, but they all share the same git history.
Key commands:
git worktree add <path> <branch>creates a new worktreegit worktree listshows all worktreesgit worktree remove <path>cleans up a worktreegit worktree pruneremoves orphaned references
Use worktrees for hotfixes, code reviews, and parallel work. Combine them with Claude Code for the ultimate parallel AI coding workflow where each Claude instance operates in complete isolation.
Stop stashing. Start using worktrees.