Git Worktrees for Parallel Development
Master parallel feature development with git worktrees. Run multiple branches simultaneously, handle urgent hotfixes without stashing, and optimize team workflows.
What you'll learn
- ✓How to run multiple feature branches in parallel using worktrees
- ✓Setting up a worktree-based development workflow
- ✓Managing shared dependencies across worktrees
- ✓Combining worktrees with CI pipelines and code review
- ✓Cleaning up and troubleshooting worktree issues
Prerequisites
- •Basic Git branching and checkout commands
- •Familiarity with working on feature branches
The Problem with Single-Branch Development
Every developer has experienced this: you are deep in a complex feature, files changed everywhere, and then Slack pings. A critical bug in production needs a hotfix right now. Your options are limited and all of them hurt.
You can git stash your work, but stashes get messy when they pile up. You can commit half-finished work with a “WIP” message, but that pollutes your commit history. You can clone the entire repository again, but that wastes disk space and time.
Git worktrees solve this cleanly. They let you check out multiple branches into separate directories, all sharing the same .git data. No duplication, no stashing, no WIP commits.
How Worktrees Enable Parallel Development
A worktree is a linked working directory backed by the same repository. Each worktree checks out a different branch, and you can work on all of them simultaneously. Changes in one worktree do not affect the others because each has its own index and working tree.
project/.git (single shared object store)
|
+-- project/ (main worktree: feature/auth)
|
+-- project-hotfix/ (linked worktree: hotfix/login-crash)
|
+-- project-review/ (linked worktree: feature/dashboard)
|
+-- project-experiment/ (linked worktree: experiment/new-api) Setting Up a Parallel Workflow
Creating your first worktree
Start from your main project directory. Create a worktree for a new feature:
# You are on feature/auth in ~/code/project
git worktree add ../project-hotfix -b hotfix/login-crash main
This creates a new directory at ../project-hotfix, checks out a new branch hotfix/login-crash from main, and links it back to the same .git directory.
# Verify your worktrees
git worktree list
# /home/dev/code/project a1b2c3d [feature/auth]
# /home/dev/code/project-hotfix d4e5f6a [hotfix/login-crash]
Working on multiple features simultaneously
Create worktrees for each parallel task:
# Worktree for reviewing a teammate's PR
git fetch origin
git worktree add ../project-review origin/feature/dashboard
# Worktree for experimenting with a new approach
git worktree add ../project-experiment -b experiment/new-api main
Now you have four separate directories, each on a different branch. Open each in its own terminal or IDE window and work on them independently.
Switching between tasks
The beauty of worktrees is that switching context means switching directories, not branches:
# Fix the hotfix
cd ../project-hotfix
vim src/auth/login.js
npm test
git add -A && git commit -m "fix: prevent crash on empty session token"
git push -u origin hotfix/login-crash
# Back to your feature
cd ../project
# Everything is exactly as you left it
No stash. No WIP commit. No lost state.
Managing Dependencies Across Worktrees
Each worktree has its own working directory, which means each needs its own node_modules, virtual environment, or build artifacts. This is the main tradeoff.
Node.js projects
cd ../project-hotfix
npm install # Install dependencies for this worktree
To save disk space, consider using pnpm with its content-addressable store. Packages are stored once globally and hard-linked into each worktree’s node_modules:
# In each worktree
pnpm install # Fast because packages are already downloaded
Python projects
cd ../project-hotfix
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
Automating setup with a script
Create a helper script to automate worktree creation with dependency installation:
#!/bin/bash
# wt-create.sh - Create a worktree with dependency setup
BRANCH=$1
DIR="../project-$(echo $BRANCH | tr '/' '-')"
git worktree add "$DIR" -b "$BRANCH" main
cd "$DIR"
# Detect project type and install dependencies
if [ -f "package.json" ]; then
npm install
elif [ -f "requirements.txt" ]; then
python -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
elif [ -f "go.mod" ]; then
go mod download
fi
echo "Worktree ready at $DIR on branch $BRANCH"
Usage:
./wt-create.sh feature/new-dashboard
Worktrees for Code Review
One of the best uses of worktrees is reviewing pull requests without leaving your current work:
# Fetch the latest remote branches
git fetch origin
# Create a worktree for the PR branch
git worktree add ../project-review-42 origin/feature/user-settings
# Open it in your editor
cd ../project-review-42
code .
# Run the test suite
npm test
# When done reviewing, clean up
cd ../project
git worktree remove ../project-review-42
You can even create a shell alias:
alias review='f() { git fetch origin && git worktree add "../review-$1" "origin/$1" && cd "../review-$1"; }; f'
# Usage
review feature/user-settings
Worktrees in CI Pipelines
Worktrees can speed up CI by avoiding full clones for each job:
# CI setup: clone once, create worktrees per job
git clone --bare https://github.com/org/repo.git repo.git
cd repo.git
# Job 1: Run tests on PR branch
git worktree add ../job-tests origin/feature/auth
cd ../job-tests && npm install && npm test
# Job 2: Build the main branch
git worktree add ../job-build main
cd ../job-build && npm install && npm run build
# Cleanup after jobs complete
git worktree remove ../job-tests
git worktree remove ../job-build
Using a bare clone as the base is especially efficient because it stores no working tree of its own.
Handling Conflicts and Edge Cases
Same branch restriction
Git prevents two worktrees from checking out the same branch:
git worktree add ../test main
# fatal: 'main' is already checked out at '/home/dev/code/project'
If you need to inspect a branch that is checked out elsewhere, use detached HEAD:
git worktree add --detach ../inspect-main main
Stale worktrees
If you delete a worktree directory manually (with rm -rf instead of git worktree remove), Git keeps stale metadata. Clean it up:
git worktree prune
Lock a worktree
If a worktree is on a network drive or external storage that might disconnect, lock it so prune does not remove it:
git worktree lock ../project-hotfix --reason "on external SSD"
git worktree unlock ../project-hotfix # when done
Best Practices for Parallel Development
-
Name worktrees consistently. Use a pattern like
project-branchtype-nameso directories are easy to identify. -
Keep worktrees as siblings. Place them next to the main repo directory, not inside it.
-
Remove worktrees when done. Stale worktrees consume disk space and clutter
git worktree list. -
Use per-worktree config. Set worktree-specific settings with
git config --worktree:
cd ../project-hotfix
git config --worktree user.email "hotfix-bot@company.com"
- Combine with direnv. Use
.envrcfiles per worktree for environment variables:
# ../project-hotfix/.envrc
export DATABASE_URL="postgres://localhost/myapp_test"
export NODE_ENV="development"
- Limit active worktrees. Having too many worktrees open defeats the purpose. Three to four concurrent worktrees is a practical maximum for most workflows.
When Not to Use Worktrees
Worktrees are not always the right tool:
- Quick branch switches where your working tree is clean: just use
git switch. - Repos with massive build artifacts where each worktree needs gigabytes of build output.
- Submodule-heavy repos where each worktree needs separate submodule initialization.
Wrap-Up
Git worktrees turn context switching from an interruption into a directory change. You keep your feature branch untouched while fixing a hotfix, reviewing a PR, or running a bisect session. The workflow scales naturally: one .git directory, multiple working trees, zero stashing. Start with one extra worktree for hotfixes and expand from there as the pattern proves its value.
Related articles
- Git Git Worktree Explained
Use git worktree to check out multiple branches at once without cloning. Speed up code review, hotfixes, and experimentation.
- Git Git Stash Tutorial: Saving Work in Progress
Learn how to use git stash to safely shelve uncommitted changes, switch contexts, and recover work using push, pop, apply, and branch workflows.
- Productivity Git Workflow Strategies for Teams
Compare Gitflow, trunk-based, GitHub Flow, and Ship/Show/Ask. Learn which git workflow fits your team, with branch naming and PR conventions.
- Git Git Rebasing Strategies for Clean Team Histories
Advanced git rebase strategies for teams: interactive rebase workflows, rebase --onto, autosquash, and policies that keep shared branches clean without rewriting public history.