Git Worktrees: Work on Multiple Branches Simultaneously

Git Worktrees - Work on Multiple Branches Simultaneously
🌿 Git Advanced Features

Git Worktrees

Work on multiple branches simultaneously — no more stashing or context switching

N+1
Branches
simultaneously
0
Stash
operations
Shared
.git history
across worktrees
Built-in
Git core
since 2.5

Introduction: The Problem Git Worktrees Solve

Every developer has faced this scenario: you're deep in the middle of implementing a feature on feature/auth-refactor, and suddenly you get a message — "critical bug in production, fix needed ASAP!" You have two options:

  1. Stash your changes, switch branches, fix the bug, commit, push, then switch back and pop the stash — hoping nothing conflicts
  2. Clone the entire repository again into a second folder and work in parallel

Both options are tedious. Git Worktrees provide an elegant built-in solution: they allow you to check out multiple branches simultaneously in separate directories, all sharing the same .git repository and history.

🗂️ How Worktrees Work

📁
my-repo/ (main)
.git/ → full history
src/
package.json
Branch: main
📁
my-repo-hotfix/
.git → (linked to main .git)
src/ (hotfix versions)
Branch: hotfix/critical-fix
📁
my-repo-feature/
.git → (linked to main .git)
src/ (feature versions)
Branch: feature/new-ui

All worktrees share one .git directory. Commits, branches, and history are always in sync.

Basic Commands

Git worktrees are managed with git worktree commands. Here are the essentials:

bash — Essential git worktree commands
# Add a new worktree for an existing branch
git worktree add ../my-repo-hotfix hotfix/critical-bug

# Add a worktree AND create a new branch at the same time
git worktree add -b feature/new-payment ../my-repo-payment main

# Add a worktree in detached HEAD state (specific commit)
git worktree add ../my-repo-review abc1234

# List all worktrees
git worktree list

# Output example:
/home/alex/my-repo          abc1234 [main]
/home/alex/my-repo-hotfix   def5678 [hotfix/critical-bug]
/home/alex/my-repo-payment  ghi9012 [feature/new-payment]

# Remove a worktree (safe — checks for uncommitted changes)
git worktree remove ../my-repo-hotfix

# Force remove even with uncommitted changes
git worktree remove --force ../my-repo-hotfix

# Prune stale worktree references (after manual deletion)
git worktree prune

# Move a worktree to a different path
git worktree move ../my-repo-hotfix ../archives/hotfix-jan2026

Real-World Example: Hotfix While Keeping Feature Work

bash — Complete hotfix workflow with worktrees
# === Scenario: You're working on feature/auth-refactor ===
cd ~/my-repo                    # your main worktree
git branch                      # shows: * feature/auth-refactor
# ... lots of uncommitted work in progress ...

# 🚨 CRITICAL BUG ALERT! Do NOT stash. Just add a worktree:
git worktree add -b hotfix/login-null-check ~/my-repo-hotfix main

# Open a new terminal and work on the hotfix
cd ~/my-repo-hotfix

# Fix the bug
vim src/auth/login.ts
git add .
git commit -m "fix: handle null user on login redirect"
git push origin hotfix/login-null-check

# Create PR and merge to main (via GitHub/GitLab/etc)
# Then merge to main locally:
git checkout main               # ← you'd do this in a 3rd worktree or here
git merge hotfix/login-null-check
git push origin main

# Clean up
git worktree remove ~/my-repo-hotfix
git branch -d hotfix/login-null-check

# Back to your feature work — nothing was interrupted!
cd ~/my-repo
# All your uncommitted changes are still here, untouched ✅

Advanced Usage: CI/CD, Code Reviews & Parallel Testing

bash — Advanced patterns
# ─── Pattern 1: Code Review Without Switching ───────────────
# Review a PR without disturbing your current work
git worktree add /tmp/review-pr-243 origin/feature/payment-v2
cd /tmp/review-pr-243
# Run the app, check behavior, leave comments
cd ~/my-repo
git worktree remove /tmp/review-pr-243

# ─── Pattern 2: Parallel Test Runs ──────────────────────────
# Run tests on main while developing on feature branch
git worktree add /tmp/test-main main
cd /tmp/test-main && npm test &     # runs in background
cd ~/my-repo && npm test &          # runs in parallel

# ─── Pattern 3: Release Branch Management ───────────────────
git worktree add ~/releases/v2.1 release/2.1
git worktree add ~/releases/v2.0 release/2.0
# Apply security patches to both simultaneously
patch_file="fix-cve-2026-001.patch"
cd ~/releases/v2.1 && git apply "../$patch_file" && git commit -am "security: apply CVE-2026-001"
cd ~/releases/v2.0 && git apply "../$patch_file" && git commit -am "security: apply CVE-2026-001"

# ─── Pattern 4: Ephemeral Worktrees for CI ──────────────────
# In a CI script — build without changing the checked-out branch
git worktree add /tmp/ci-build "$CI_COMMIT_SHA"
cd /tmp/ci-build
npm ci && npm run build && npm test
git worktree remove /tmp/ci-build

⚠️ Important Rules & Constraints

🚫 No Duplicate Checkouts

The same branch cannot be checked out in two worktrees simultaneously. Git enforces this to prevent conflicting HEAD pointers. You'll get: fatal: 'feature/x' is already checked out

📦 Shared Object Store

All worktrees share a single .git object database. Git operations like fetch, log, and blame work identically in any worktree — they all see the same refs.

🔧 IDE Support

Most modern IDEs (VS Code, JetBrains) support worktrees. Each worktree directory is a separate "project" in your IDE. VS Code's Remote - Containers also works with worktrees.

💾 Disk Space

Worktrees don't duplicate the .git objects directory. Only the working files are duplicated. A worktree of a 500MB repo uses ~100-200MB extra (just working files), not 500MB.

Worktrees vs Alternatives

⚖️ Comparison: Worktrees vs Other Approaches

Approach Context Switch Disk Usage Parallel Work Best For
git worktree✅ None✅ Minimal✅ True parallelMost use cases
git stash⚠️ Full switch✅ None❌ Sequential onlyQuick, temporary
Second clone✅ None❌ Full duplication✅ True parallelIsolated experiments
WIP commit + switch⚠️ Full switch✅ None❌ Sequential onlyWhen stash isn't clean

Scripting Worktrees for Productivity

bash — Shell helper functions for worktrees
# Add to your ~/.bashrc or ~/.zshrc

# Create a worktree for a PR review
gwt-review() {
  local branch="$1"
  local dir="/tmp/review-$(basename $branch)"
  git fetch origin "$branch"
  git worktree add "$dir" "origin/$branch"
  echo "Reviewing at: $dir"
  cd "$dir"
}

# Create a worktree based on current repo name
gwt-add() {
  local branch="$1"
  local repo_name=$(basename "$(git rev-parse --show-toplevel)")
  local short_branch=$(echo "$branch" | sed 's/[/:]/-/g')
  local dir="../$(repo_name)-$short_branch"
  git worktree add -b "$branch" "$dir" main
  echo "Worktree at: $dir"
  cd "$dir"
}

# List worktrees in a nice table
gwt-list() {
  git worktree list --porcelain | awk '
    /^worktree/ { path=substr($0,10) }
    /^branch/   { branch=substr($0,8) }
    /^HEAD/     { head=substr($0,6,7) }
    /^$/        { printf "%-50s %-30s %s
", path, branch, head; path=branch=head="" }
  '
}

# Clean up all /tmp/review-* worktrees
gwt-clean-reviews() {
  git worktree list --porcelain | grep -A1 '^worktree /tmp/review-'     | grep '^worktree' | awk '{print $2}'     | xargs -I{} git worktree remove "{}"
}

Worktrees with Monorepos and Node.js/npm

bash — Handling node_modules with worktrees
# Each worktree has its own node_modules — this is usually fine
# But to avoid reinstalling, you can use npm ci with caching:

git worktree add ../my-repo-feature feature/new-ui
cd ../my-repo-feature
npm ci   # Install dependencies for this branch

# With pnpm — it uses a shared store, so adding a worktree is fast!
git worktree add ../my-repo-feature feature/new-ui
cd ../my-repo-feature
pnpm install  # Links from global pnpm store — very fast

# With yarn workspaces / pnpm workspaces in a monorepo:
# Worktrees work great — each worktree gets its own node_modules
# but shares the package cache

# .gitignore each worktree's external node_modules if needed:
# Add to .gitignore:
../*-worktree/
../*-hotfix/
../*-feature/

💡 Best Practices & Pro Tips

📂 Naming Convention
Use descriptive names: ../repo-hotfix, ../repo-review-123, ../repo-release-2.1. Makes gwt-list output readable.
🧹 Regular Cleanup
Run git worktree prune regularly (or as a git hook) to clean stale references. Also add temporary worktree paths to your global ~/.gitignore.
🔗 IDE Integration
Open each worktree as a separate VS Code window (code /path/to/worktree) or use JetBrains' "Open Directory" for parallel IDEs on the same codebase.
📍 Location Strategy
Keep sibling worktrees next to the main repo: ~/projects/my-repo~/projects/my-repo-hotfix. Avoids deep nesting and keeps related work grouped.

Summary

Git Worktrees are a powerful but underutilized feature available in every modern Git installation. They eliminate the friction of context-switching between branches by allowing multiple checkouts of the same repository to coexist simultaneously. Whether you're handling emergency hotfixes, reviewing pull requests, running parallel tests, or managing multiple release branches, worktrees provide a clean and efficient solution.

Start small: next time you need to context-switch, try git worktree add instead of stashing. Once you build the habit, you'll find yourself using worktrees as a core part of your daily Git workflow.

Post a Comment

Previous Post Next Post