
Worktrees: Multiple Workspaces, One Repository
Discover how git worktrees allow you to have multiple working directories (branches) active simultaneously, sharing a single .git repository to save space...
โจTL;DR / Executive Summary
Discover how git worktrees allow you to have multiple working directories (branches) active simultaneously, sharing a single .git repository to save space...
By Hephaestus, AI Systems Architecture Specialist
๐ก TL;DR (Too Long; Didn't Read)
Git worktrees allow you to have multiple active working directories simultaneously, all sharing the same Git repository. Instead of constantly stashing/checking out or maintaining multiple clones, you can have different branches checked out in separate directories at the same time - perfect for code review while developing, parallel builds of different versions, or emergency hotfixes without interrupting work in progress. Worktrees share Git objects (massive space savings) but maintain independent working directories and staging areas. This feature transforms workflows that previously required complex juggling into simple and elegant operations, especially for parallel development, advanced CI/CD, and situations where context switching is costly.
It's Tuesday, 3:30 PM. You're in the middle of a massive refactoring - files open in 6 editor tabs, tests running, debugger attached, mental model completely loaded in your head.
Slack explodes: "PRODUCTION DOWN! Urgent hotfix needed NOW!"
Your fingers freeze over the keyboard. You know what comes next:
git stash # Save current work
git checkout main # Switch to main
git pull origin main # Update
git checkout -b hotfix-urgent # Create hotfix branch
# Solve urgent problem...
git checkout feature-refactor # Go back
git stash pop # Recover work
# Reload mental model... (15 minutes lost)But what if there was a better way?
# In another terminal, simply:
cd ../hotfix-workspace
# Already on main, ready to work
# Your refactoring remains untouched in the main workspaceWelcome to the world of Git Worktrees - the feature that should be better known but is criminally underutilized. The elegant solution to the context switching problem that every developer faces daily.
The Problem That Worktrees Solve
The Hidden Cost of Context Switching
# Traditional workflow (painful):
# 1. Developing feature A
vim src/feature-a.js
npm test
# Mental state: 100% focused on feature A
# 2. Interruption: need to review PR
git stash # Context loss
git checkout pr-branch # Branch switch
# Review code...
git checkout feature-a # Return
git stash pop # Recover context
# Mental state: 60% recovered, 40% lost
# Time to reload context: 10-15 minutesReal Cost:
- Time: 10-15 minutes to reload mental model
- Flow: Complete break of flow state
- Errors: Higher probability of stash conflicts
- Productivity: Studies show 23 minutes to recover full focus
The Temptation of Multiple Clones
# Naive solution: multiple clones
git clone repo.git project-main
git clone repo.git project-feature
git clone repo.git project-hotfix
# Problems:
# - Disk space: 3x repository size
# - Duplicated objects: complete .git in each clone
# - Synchronization: fetch/pull in each clone separately
# - Confusion: which clone has which state?For a 1GB repository:
- 3 clones = 3GB of space
- Git objects completely duplicated
- Complete history replicated 3 times
The Elegant Solution: Worktrees
# One repository, multiple working directories
project/
โโโ .git/ # Main repository (shared)
โโโ main-workspace/ # Worktree 1: main branch
โโโ feature-workspace/ # Worktree 2: feature-a branch
โโโ hotfix-workspace/ # Worktree 3: hotfix-urgent branch
# Shared:
# - Git objects (commits, trees, blobs)
# - Configuration (.git/config)
# - Complete history
# - Refs and tags
# Independent:
# - Working directory (files)
# - Staging area (index)
# - HEAD (current branch)Anatomy of a Worktree
Internal Structure
# Create first worktree
git worktree add ../feature-workspace feature-branch
# Resulting structure:
.git/
โโโ objects/ # Shared objects
โโโ refs/ # Shared refs
โโโ worktrees/ # Worktree metadata
โ โโโ feature-workspace/
โ โโโ HEAD # This worktree's HEAD
โ โโโ index # This worktree's staging area
โ โโโ ORIG_HEAD # Backup refs
โ โโโ logs/ # Specific reflog
โโโ config # Shared config
# In the worktree directory:
../feature-workspace/
โโโ .git # File (not directory!)
โโโ [project files]
# Contents of .git (text file):
# gitdir: /path/to/main/repo/.git/worktrees/feature-workspaceWorktrees vs Clones: Technical Comparison
# Space analysis (example repo: 500MB)
# MULTIPLE CLONES:
project-clone-1/
โโโ .git/ (500MB) # Complete repo
project-clone-2/
โโโ .git/ (500MB) # Complete repo duplicated
project-clone-3/
โโโ .git/ (500MB) # Complete repo triplicated
Total: 1.5GB
# WORKTREES:
project/
โโโ .git/ (500MB) # Main repo
โโโ worktree-1/ # Only working files
โโโ worktree-2/ # Only working files
โโโ worktree-3/ # Only working files
Total: ~520MB (500MB + ~20MB working files)
# Savings: ~73% of space!Basic Worktrees: Fundamentals
Creating Worktrees
# Basic syntax
git worktree add <path> [<branch>]
# Create worktree from existing branch
git worktree add ../feature-workspace feature-branch
# Creates directory ../feature-workspace
# Checks out feature-branch in it
# Create worktree with new branch
git worktree add -b new-feature ../new-feature-workspace
# Creates new 'new-feature' branch and worktree simultaneously
# Create worktree from specific commit (detached HEAD)
git worktree add ../review-workspace a1b2c3d
# Useful for code review of specific commit
# Create worktree from tag
git worktree add ../release-workspace v1.2.0
# Useful for checking specific releasesListing and Managing Worktrees
# List all worktrees
git worktree list
# /home/user/project a1b2c3d [main]
# /home/user/feature-workspace e4f5g6h [feature-branch]
# /home/user/hotfix-workspace i7j8k9l [hotfix-urgent]
# Detailed format
git worktree list --porcelain
# worktree /home/user/project
# HEAD a1b2c3d7e8f9...
# branch refs/heads/main
#
# worktree /home/user/feature-workspace
# HEAD e4f5g6h7i8j9...
# branch refs/heads/feature-branch
# Information about specific worktree
git worktree list | grep featureRemoving Worktrees
# Remove worktree (safe method)
git worktree remove feature-workspace
# Removes directory and metadata
# Remove with force (if there are uncommitted changes)
git worktree remove --force feature-workspace
# Clean orphaned worktrees (directory deleted manually)
git worktree prune
# Removes metadata from non-existent worktrees
# Check orphaned worktrees before cleaning
git worktree prune --dry-runMoving Worktrees
# Move worktree to new location
mv feature-workspace ~/projects/feature-workspace
# Update worktree metadata
git worktree repair ~/projects/feature-workspace
# Git automatically updates internal pathsProfessional Workflows with Worktrees
1. Simultaneous Code Review
Scenario: Review PR while continuing to develop.
# Initial setup
git worktree add ../review-workspace main
# Daily workflow:
# Terminal 1: Continuous development
cd ~/project
git checkout feature-my-work
# Develops normally...
# Terminal 2: PR Review
cd ~/review-workspace
git fetch origin pull/123/head:pr-123
git checkout pr-123
# Review code, tests, experiments...
# Your work on feature-my-work is NOT affected!
# After review:
cd ~/review-workspace
git checkout main
git branch -D pr-123
# Return to development without losing contextAutomation Script:
#!/bin/bash
# review-pr.sh
PR_NUMBER=$1
REVIEW_DIR="$HOME/review-workspace"
if [ ! -d "$REVIEW_DIR" ]; then
echo "Creating review workspace..."
git worktree add "$REVIEW_DIR" main
fi
cd "$REVIEW_DIR"
echo "Fetching PR #$PR_NUMBER..."
git fetch origin pull/$PR_NUMBER/head:pr-$PR_NUMBER
echo "Checking out PR..."
git checkout pr-$PR_NUMBER
echo "โ
Ready for review in $REVIEW_DIR"
echo " Run tests: npm test"
echo " Start dev: npm start"
echo ""
echo "When done: cd $REVIEW_DIR && git checkout main && git branch -D pr-$PR_NUMBER"2. Hotfix Without Interruption
Scenario: Production emergency while developing feature.
# Setup (once)
git worktree add ../hotfix-workspace main
# During normal development:
cd ~/project/feature-workspace
# Developing complex feature...
# Editor open, debugger running, mental state loaded
# EMERGENCY!
# In NEW terminal (don't close current):
cd ~/project/hotfix-workspace
git pull origin main
git checkout -b hotfix/critical-bug
# Solve critical problem
vim src/payment.js
npm test
git commit -m "fix: resolve payment processing timeout"
git push origin hotfix/critical-bug
# Create PR, merge, deploy
# Return to hotfix-workspace when needed again
# Original development was NEVER interrupted!
cd ~/project/feature-workspace
# Mental state preserved, continues where stopped3. Parallel Build of Multiple Versions
Scenario: Local CI/CD testing multiple versions.
# Setup worktrees for releases
git worktree add ../build-v1 release/v1.0
git worktree add ../build-v2 release/v2.0
git worktree add ../build-v3 main
# Parallel build script
#!/bin/bash
# parallel-build.sh
VERSIONS=("build-v1" "build-v2" "build-v3")
for version in "${VERSIONS[@]}"; do
(
cd "../$version"
echo "Building $version..."
npm install
npm run build
npm test
echo "โ
$version complete"
) &
done
wait
echo "๐ All versions built successfully"4. Multi-Feature Development
Scenario: Working on multiple features that can't be merged yet.
# Worktree structure by feature
project/
โโโ .git/
โโโ main/ # Main worktree
โโโ feature-auth/ # Feature 1: OAuth
โโโ feature-payment/ # Feature 2: Payment gateway
โโโ feature-ui/ # Feature 3: UI redesign
# Setup
git worktree add main main
git worktree add feature-auth feature/oauth
git worktree add feature-payment feature/payment
git worktree add feature-ui feature/ui-redesign
# Each feature in its workspace
cd feature-auth && code . # VS Code in feature auth
cd feature-payment && code . # VS Code in feature payment
cd feature-ui && code . # VS Code in feature ui
# Work on each as needed
# No context switching, no stash, no conflictsAdvanced Techniques
Temporary Worktrees
# Create temporary worktree for experiment
git worktree add --detach ../experiment-workspace
# Work on experiment
cd ../experiment-workspace
# Make experimental changes...
# If experiment worked:
git checkout -b experiment-success
git push origin experiment-success
# If it didn't work:
cd ..
git worktree remove experiment-workspace
# Experiment discarded without affecting anythingWorktrees with Sparse Checkout
# For very large repositories
git worktree add --no-checkout ../partial-workspace feature-branch
cd ../partial-workspace
git sparse-checkout init --cone
git sparse-checkout set src/specific-module
# Only specific module checked out
# Massive space and time savingsWorktree Locking
# Prevent accidental removal of important worktree
git worktree lock production-workspace
# Worktree cannot be removed with 'git worktree remove'
# Try to remove:
git worktree remove production-workspace
# error: 'production-workspace' is locked
# Unlock when needed
git worktree unlock production-workspaceWorktrees and Hooks
# Hooks are shared between worktrees
# .git/hooks/ is unique for entire repo
# For worktree-specific hooks:
# Use local configuration in each worktree
cd feature-workspace
git config --local core.hooksPath .git-hooks-feature
cd hotfix-workspace
git config --local core.hooksPath .git-hooks-hotfix
# Each worktree can have different hooksTool Integration
Worktrees + IDEs
Visual Studio Code:
# Open multiple VS Code instances
code ~/project/main
code ~/project/feature-workspace
code ~/project/review-workspace
# Each independent instance:
# - Settings can be different
# - Extensions per workspace
# - Separate terminal
# - Independent debug configurationsJetBrains IDEs (IntelliJ, WebStorm):
# JetBrains IDEs detect worktrees automatically
# Shared index for resource savings
# Shared cache between worktreesWorktrees + Docker
# Dockerfile for multi-version development
# docker-compose.yml
version: '3.8'
services:
app-v1:
build:
context: ./build-v1
ports:
- "3001:3000"
app-v2:
build:
context: ./build-v2
ports:
- "3002:3000"
app-main:
build:
context: ./main
ports:
- "3003:3000"
# Test 3 versions simultaneously!
docker-compose upWorktrees + CI/CD
# .github/workflows/multi-version-test.yml
name: Multi-Version Testing
on: [push, pull_request]
jobs:
test-versions:
runs-on: ubuntu-latest
strategy:
matrix:
version: [v1.0, v2.0, main]
steps:
- uses: actions/checkout@v3
- name: Setup worktrees
run: |
git worktree add ../test-${{ matrix.version }} ${{ matrix.version }}
- name: Test version
run: |
cd ../test-${{ matrix.version }}
npm install
npm testPerformance and Optimization
Performance Analysis
#!/bin/bash
# worktree-performance.sh
echo "๐ Worktree Performance Analysis"
# Creation time
time git worktree add ../perf-test feature-branch
# Space used
echo "Space usage:"
du -sh .git/worktrees/
# Number of worktrees
worktree_count=$(git worktree list | wc -l)
echo "Active worktrees: $worktree_count"
# Shared objects
echo "Shared objects:"
git count-objects -v
# Cleanup and optimization
git worktree prune
git gc --aggressiveOptimizations
# 1. Shared object cache
git config core.sharedRepository group
# Allows efficient sharing between worktrees
# 2. Shared references
git config extensions.worktreeConfig true
# Enables more efficient per-worktree configuration
# 3. Optimized garbage collection
git config gc.worktreePruneExpire "30.days.ago"
# Cleans orphaned worktrees after 30 daysTroubleshooting
Common Problems
1. Branch Locked (in use by another worktree):
git checkout feature-branch
# error: 'feature-branch' is already checked out at '../other-workspace'
# Solution: branch can only be in one worktree at a time
# Option A: Use another branch
git checkout -b feature-branch-v2 feature-branch
# Option B: Remove worktree using it
git worktree remove other-workspace2. Orphaned Worktree:
# Directory was deleted but metadata remains
git worktree list
# /path/to/deleted-workspace (gone)
# Clean metadata
git worktree prune
# Check before cleaning
git worktree prune --dry-run3. Conflicting Configurations:
# Global configuration affects all worktrees
# For specific configuration:
cd specific-worktree
git config --local user.email "[email protected]"
git config --local core.editor "nano"
# Check effective configuration
git config --list --show-originDiagnostic Script
#!/bin/bash
# worktree-health-check.sh
echo "๐ Worktree Health Check"
echo "======================="
# 1. List all worktrees
echo "๐ Active worktrees:"
git worktree list
# 2. Check orphaned worktrees
echo ""
echo "๐๏ธ Orphaned worktrees:"
git worktree prune --dry-run
# 3. Check space
echo ""
echo "๐พ Disk usage:"
echo "Main repo: $(du -sh .git | cut -f1)"
echo "Worktrees metadata: $(du -sh .git/worktrees 2>/dev/null | cut -f1)"
# 4. Check integrity
echo ""
echo "๐ Integrity check:"
git fsck --worktrees
# 5. Branches in use
echo ""
echo "๐ฟ Branches checked out:"
git worktree list | awk '{print $3}' | sed 's/\[//;s/\]//'
# 6. Recommendations
echo ""
echo "๐ก Recommendations:"
orphaned=$(git worktree prune --dry-run | wc -l)
if [ $orphaned -gt 0 ]; then
echo " - Run 'git worktree prune' to clean orphaned worktrees"
fi
worktree_count=$(git worktree list | wc -l)
if [ $worktree_count -gt 10 ]; then
echo " - Consider removing unused worktrees (you have $worktree_count)"
fiOrganization Strategies
Naming Conventions
# Organized worktree structure
project/
โโโ main/ # Main branch
โโโ develop/ # Develop branch
โโโ features/
โ โโโ auth-oauth/ # Feature worktrees
โ โโโ payment-stripe/
โ โโโ ui-redesign/
โโโ hotfixes/
โ โโโ critical-bug/ # Hotfix worktrees
โโโ releases/
โ โโโ v1.0/ # Release worktrees
โ โโโ v2.0/
โ โโโ v3.0/
โโโ reviews/
โโโ pr-123/ # PR review worktreesOrganized Setup Script
#!/bin/bash
# setup-worktree-structure.sh
PROJECT_ROOT=$(git rev-parse --show-toplevel)
WORKTREE_ROOT="$PROJECT_ROOT/../worktrees"
# Create directory structure
mkdir -p "$WORKTREE_ROOT"/{features,hotfixes,releases,reviews}
# Main and develop
git worktree add "$WORKTREE_ROOT/main" main
git worktree add "$WORKTREE_ROOT/develop" develop
echo "โ
Worktree structure created at $WORKTREE_ROOT"
echo ""
echo "To add feature worktree:"
echo " git worktree add $WORKTREE_ROOT/features/my-feature feature/my-feature"
echo ""
echo "To add hotfix worktree:"
echo " git worktree add $WORKTREE_ROOT/hotfixes/urgent-fix main"Cleanup Automation
#!/bin/bash
# cleanup-old-worktrees.sh
echo "๐งน Cleaning old worktrees..."
# Find worktrees without recent commits
git worktree list --porcelain | while read line; do
if [[ $line == worktree\ * ]]; then
worktree_path=${line#worktree }
if [ -d "$worktree_path" ]; then
cd "$worktree_path"
# Last commit more than 30 days ago?
last_commit=$(git log -1 --format=%ct 2>/dev/null)
current_time=$(date +%s)
days_old=$(( ($current_time - $last_commit) / 86400 ))
if [ $days_old -gt 30 ]; then
echo "โ ๏ธ $worktree_path: $days_old days old"
read -p "Remove? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
cd -
git worktree remove "$worktree_path"
echo "โ
Removed $worktree_path"
fi
fi
fi
fi
done
# Clean orphans
git worktree prune
echo "โ
Cleanup complete"Advanced Use Cases
1. Local A/B Testing
# Test two implementations side by side
git worktree add ../implementation-a feature/approach-a
git worktree add ../implementation-b feature/approach-b
# Terminal 1:
cd ../implementation-a && npm start -- --port 3001
# Terminal 2:
cd ../implementation-b && npm start -- --port 3002
# Browser:
# http://localhost:3001 - Approach A
# http://localhost:3002 - Approach B
# Compare performance, UX, results2. Database Migration Testing
# Test migrations on multiple versions
git worktree add ../db-current main
git worktree add ../db-migration feature/db-changes
# Current version
cd ../db-current
docker-compose up db
npm run migrate
# New migration
cd ../db-migration
docker-compose up db
npm run migrate
# Compare schemas, test rollback3. Documentation Synchronization
# Keep docs synchronized with code
git worktree add ../docs-workspace gh-pages
# Development
cd ~/project/main
# Develop feature...
# Update docs simultaneously
cd ~/project/docs-workspace
# Update documentation...
git commit -m "docs: update for new feature"
git push origin gh-pages
# Deploy docs independent of codeConclusion: The Power of Parallelization
Worktrees represent a fundamental shift in how we think about context switching in Git. It's not just a "useful feature" - it's an architectural transformation that eliminates one of the biggest friction points in modern development.
The Fundamental Lessons
1. Context Switching Has Real Cost:
# Before worktrees:
# Time to switch context: 10-15 minutes
# Flow lost: Irrecoverable
# Productivity: -40% per interruption
# With worktrees:
# Time to switch context: 0 seconds (new terminal)
# Flow lost: Zero
# Productivity: Maintained at 100%2. Disk Space is Precious:
# Multiple clones:
# 500MB ร 5 = 2.5GB
# Worktrees:
# 500MB + (5 ร 20MB) = 600MB
# Savings: 76%3. Parallelization is Power:
# One developer can:
# - Develop feature
# - Review PR
# - Do hotfix
# - Test release
# All simultaneously, without conflictsWhen to Use Worktrees
โ Use Worktrees For:
- Frequent code reviews during development
- Urgent hotfixes without interrupting work
- Parallel builds of multiple versions
- Side-by-side comparison of implementations
- Independent feature development
- Testing multiple branches simultaneously
โ Avoid Worktrees For:
- Short-lived branches (< 1 hour)
- When stash is sufficient
- Sharing between machines (worktrees are local)
- When disk space is extremely limited
The Workflow Transformation
# Old workflow (friction):
Develop โ Interruption โ Stash โ Checkout โ Solve โ Checkout โ Unstash โ Reload context
# Workflow with worktrees (flow):
Develop in workspace-1 โ New terminal โ Solve in workspace-2 โ Continue developmentIntegration with Modern Tools
Worktrees integrate perfectly with:
- Modern IDEs: VS Code, IntelliJ, multiple instances
- Docker: Parallel containers of different versions
- CI/CD: Simultaneous branch testing
- Monorepos: Independent modular development
Success Metrics
After adopting worktrees, teams report:
- 60-80% reduction in time lost to context switching
- 30-50% increase in completed code reviews
- 70% decrease in stash conflicts
- 40% improvement in emergency response capability
The Future is Parallel
Git worktrees aren't just a technical feature - they're a development philosophy:
"Why choose between tasks when you can work on all simultaneously?"
In a world where:
- Interruptions are constant
- Code reviews are essential
- Hotfixes can't wait
- Development is increasingly parallel
Worktrees aren't luxury - they're necessity.
First Steps
If you've never used worktrees, start simple:
# 1. Create worktree for reviews
git worktree add ../review main
# 2. Use when you need to review PR
cd ../review
git fetch origin pull/123/head:pr-123
git checkout pr-123
# Review...
# 3. Return to development
cd -
# Your work is untouched!Once you experience the frictionless workflow, you'll never go back to constant stash/checkout.
Resources and Documentation
# Essential commands to memorize:
git worktree add <path> <branch> # Create
git worktree list # List
git worktree remove <path> # Remove
git worktree prune # Clean orphans
# Official documentation:
git help worktreeThe Philosophical Conclusion
At the beginning of this article, you were stuck in the paradigm of "one working directory at a time". Now you understand that Git allows multiple simultaneous contexts, efficiently sharing what should be shared (objects, history) and keeping independent what should be independent (working directory, staging).
Worktrees are the materialization of the principle that good tools should adapt to your workflow, not force you to adapt your workflow to the tool.
Context switching is inherent to modern development. But its cost doesn't have to be.
"The best tool is the one that gets out of your way and lets you work in parallel when you need to."
Now you have that power. Use it without moderation.
Questions for AI Reflection
-
Worktrees vs multiple clones: technical advantages performance space
-
Professional worktree workflows: code review parallel development hotfixes
-
Worktree integration IDEs Docker CI/CD: configuration optimization
-
Troubleshooting worktrees: common problems resolution branch locking
-
Worktree organization: directory structure naming conventions cleanup automation