Multi-Worktree Development - Comprehensive Guide
Advanced patterns for developing across multiple Git worktrees simultaneously.
Table of Contents
-
Parallel Development Workflows
-
Dependency Management
-
File Synchronization
-
Database and Service Management
-
Testing Workflows
-
Build Artifact Management
-
Team Collaboration
-
Performance and Optimization
- Parallel Development Workflows
Benefits of Parallel Development
Working on multiple branches simultaneously eliminates:
-
Context switching overhead
-
IDE reindexing delays
-
Stashing/committing incomplete work
-
Mental context loss
Setting Up Multiple Worktrees
Create worktrees for different features
gw add feat/user-auth gw add feat/payment-gateway gw add feat/email-notifications
List all worktrees
gw list
Managing Mental Context
Strategy 1: Dedicated terminals
Terminal 1: User Auth
gw cd feat/user-auth npm run dev
Terminal 2: Payment Gateway
gw cd feat/payment-gateway npm run dev
Strategy 2: Terminal multiplexer (tmux)
Create named sessions
tmux new -s auth gw cd feat/user-auth
tmux new -s payments gw cd feat/payment-gateway
Switch between sessions
tmux attach -t auth tmux attach -t payments
Strategy 3: IDE workspaces
VS Code multi-root workspace:
{ "folders": [ {"name": "Auth Feature", "path": "../feat/user-auth"}, {"name": "Payments", "path": "../feat/payment-gateway"} ] }
Quick Context Switching
Fast navigation with partial matching
gw cd auth # Matches feat/user-auth gw cd pay # Matches feat/payment-gateway
- Dependency Management
Understanding the Problem
Each worktree has independent working files, including node_modules :
repo.git/ ├── main/ │ └── node_modules/ # ~500MB ├── feat/user-auth/ │ └── node_modules/ # ~500MB (duplicate!) └── feat/payment-gateway/ └── node_modules/ # ~500MB (duplicate!)
With 5 worktrees: 2.5GB of duplicated dependencies!
Strategy 1: Accept Duplication (Simplest)
Pros: Full isolation, no conflicts Cons: Disk space usage
Each worktree installs independently
gw add feat/new-feature gw cd feat/new-feature npm install
Best for: Testing different dependency versions, small projects.
Strategy 2: Use pnpm (Recommended)
pnpm uses a content-addressable store that deduplicates packages:
Install pnpm
npm install -g pnpm
In each worktree
gw cd feat/user-auth pnpm install # Uses shared store
gw cd feat/payment-gateway pnpm install # Reuses cached packages
Result: Near-zero duplication, full isolation.
Strategy 3: Symlink node_modules (Advanced)
Warning: Only works if all worktrees need identical dependencies.
In feature worktree
gw cd feat/user-auth rm -rf node_modules ln -s ../main/node_modules node_modules
Risks:
-
Package version conflicts
-
Native modules may break
-
Hoisting issues
Best for: Read-only testing, identical environments.
Strategy 4: Post-Add Hook for Auto-Install
gw init --post-add "npm install"
Now every gw add automatically installs dependencies.
- File Synchronization
Using gw sync
Sync files between worktrees without recreating them:
Sync all autoCopyFiles from config
gw sync feat/user-auth
Sync specific file from main to feature branch
gw sync feat/user-auth .env
Sync from specific source
gw sync --from staging feat/user-auth .env
Sync multiple files
gw sync feat/user-auth .env secrets/ config/local.json
Common Sync Patterns
Pattern 1: Update secrets across all worktrees
After updating .env in main - sync autoCopyFiles to all worktrees
for worktree in $(gw list | grep -v main | awk '{print $1}' | xargs -n1 basename); do gw sync "$worktree" done
Or sync specific file
for worktree in $(gw list | grep -v main | awk '{print $1}' | xargs -n1 basename); do gw sync "$worktree" .env done
Pattern 2: Propagate config changes
Updated shared config in main
gw cd feat/user-auth gw sync --from main feat/user-auth config/shared.json
Pattern 3: Hot-swap environment
Test feature with production-like config
gw sync --from production-mirror feat/user-auth .env
Dry Run Mode
Preview what would be synced:
gw sync --dry-run feat/user-auth .env secrets/
- Database and Service Management
Database Isolation Strategies
Strategy 1: Separate databases per worktree
In feat/user-auth/.env
DATABASE_URL=postgresql://localhost:5432/myapp_auth
In feat/payment-gateway/.env
DATABASE_URL=postgresql://localhost:5432/myapp_payments
Strategy 2: Docker Compose per worktree
Create docker-compose.worktree.yml :
version: '3.8' services: db: image: postgres:15 ports: - "${DB_PORT:-5432}:5432" environment: POSTGRES_DB: myapp_${WORKTREE_NAME:-dev}
In each worktree
export WORKTREE_NAME=$(basename $PWD) export DB_PORT=5433 # Different port per worktree docker-compose -f docker-compose.worktree.yml up -d
Strategy 3: Shared database with schema prefixes
-- feat/user-auth uses schema: auth_feature CREATE SCHEMA auth_feature;
-- feat/payment-gateway uses schema: payments_feature CREATE SCHEMA payments_feature;
Port Management
Avoid port conflicts between worktrees:
main/.env
PORT=3000 DB_PORT=5432
feat/user-auth/.env
PORT=3001 DB_PORT=5433
feat/payment-gateway/.env
PORT=3002 DB_PORT=5434
Service Orchestration
Running frontend and backend in separate worktrees:
Terminal 1: API (main branch)
gw cd main npm run dev:api # Port 3001
Terminal 2: Frontend (feature branch)
gw cd feat/new-ui API_URL=http://localhost:3001 npm run dev:web # Port 3000
- Testing Workflows
Parallel Testing Across Environments
Test the same feature in multiple environments:
Create test worktrees
gw add test-node18 --force gw add test-node20 --force
Terminal 1: Node 18
gw cd test-node18 nvm use 18 npm install && npm test
Terminal 2: Node 20
gw cd test-node20 nvm use 20 npm install && npm test
CI/CD Integration
GitHub Actions with worktrees:
jobs: test: strategy: matrix: node: [18, 20, 22] steps: - uses: actions/checkout@v4 - name: Setup Node ${{ matrix.node }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} - run: npm install - run: npm test
Local simulation:
#!/bin/bash
test-matrix.sh
for version in 18 20 22; do gw add "test-node$version" --force ( gw cd "test-node$version" nvm use "$version" npm install npm test ) & done wait echo "All tests complete"
Test Isolation
Each worktree can have different test configurations:
In feat/user-auth
npm test -- --testPathPattern="auth"
In feat/payment-gateway
npm test -- --testPathPattern="payment"
- Build Artifact Management
Separate Build Outputs
Each worktree maintains independent build artifacts:
repo.git/ ├── main/ │ └── dist/ # Production build ├── feat/user-auth/ │ └── dist/ # Feature build └── feat/payment-gateway/ └── dist/ # Different feature build
Sharing Build Caches
Turborepo/Nx caching:
Turbo's cache is shared automatically
gw cd feat/user-auth pnpm turbo build # Fast: uses cache from main
Manual cache sharing:
Share .next/cache between worktrees
ln -s ../main/.next/cache .next/cache
Clean Build Strategies
When you need guaranteed clean builds:
Remove build artifacts
rm -rf dist/ .next/ build/
Fresh install and build
rm -rf node_modules/ npm install npm run build
- Team Collaboration
Code Review Workflows
Reviewer worktree pattern:
Create worktree from PR branch
gw add review-pr-123 gw cd review-pr-123
Review code, run tests
npm install npm test npm run dev # Manual testing
Leave review comments
...
Clean up
gw remove review-pr-123
Pair Programming
Each developer in their own worktree:
Developer A
gw add pair/feature-x-alice gw cd pair/feature-x-alice
Work on frontend...
Developer B
gw add pair/feature-x-bob gw cd pair/feature-x-bob
Work on backend...
Sync changes via git
git pull origin pair/feature-x
Demo Environments
One worktree per demo:
Create demo worktrees
gw add demo/client-a gw add demo/client-b
Each with different configuration
demo/client-a/.env
FEATURE_FLAGS=clientA
demo/client-b/.env
FEATURE_FLAGS=clientB
- Performance and Optimization
Monitoring Disk Usage
Check worktree sizes
du -sh /path/to/repo.git/*/
Find large node_modules
du -sh /path/to/repo.git/*/node_modules/ | sort -h
Cleanup Strategies
Quick cleanup:
If you need to quickly remove all temporary worktrees:
Preview what would be removed
gw prune --clean --dry-run
Remove all worktrees that are clean (no uncommitted/unpushed changes)
gw prune --clean
This is useful when:
-
Switching between projects
-
Low on disk space
-
Want to start fresh with minimal worktrees
-
Before archiving a project
Age-based cleanup (regular maintenance):
Remove all safe worktrees (default)
gw clean --dry-run # Preview gw clean # Remove
Or remove only worktrees older than configured threshold (default: 7 days)
gw clean --use-autoclean-threshold --dry-run # Preview old worktrees gw clean --use-autoclean-threshold # Remove old worktrees
Prune stale references:
Clean up administrative data for deleted worktrees
gw prune
Resource Balancing
Limit concurrent worktrees:
-
Development machine: 3-5 active worktrees
-
CI machine: As many as needed (ephemeral)
Memory considerations:
-
Each running dev server uses memory
-
Each node_modules uses disk space
-
Database containers use memory + disk
Recommended setup:
Keep essential worktrees
main/ # Always ready feat/current/ # Active feature review/ # Code review (temporary) hotfix/ # Emergency fixes (temporary)
When NOT to Use Multiple Worktrees
Consider alternatives when:
-
Single small fix → Just commit and switch back
-
Same file being edited → Use branches instead
-
Limited disk space → Use branch switching
-
Team uses different workflow → Align first
Summary
You now understand:
-
✅ Managing parallel development workflows effectively
-
✅ Dependency strategies (pnpm recommended)
-
✅ Keeping files in sync with gw sync
-
✅ Database and service isolation patterns
-
✅ Parallel testing across environments
-
✅ Build artifact management
-
✅ Team collaboration patterns
-
✅ Performance optimization techniques
Next Steps
-
Set up pnpm for efficient dependency management
-
Configure post-add hooks for automatic setup
-
Create team guidelines for worktree usage
-
Implement cleanup automation
Additional Resources
-
Sharing Dependencies Example
-
Parallel Testing Example
-
Database Management Example
-
Service Orchestration Example
Part of the gw-tools skills collection