Skip to content
Codeloom
Git

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.

·7 min read · By Codeloom
Intermediate 12 min read

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)
Parallel development with worktrees

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

  1. Name worktrees consistently. Use a pattern like project-branchtype-name so directories are easy to identify.

  2. Keep worktrees as siblings. Place them next to the main repo directory, not inside it.

  3. Remove worktrees when done. Stale worktrees consume disk space and clutter git worktree list.

  4. Use per-worktree config. Set worktree-specific settings with git config --worktree:

cd ../project-hotfix
git config --worktree user.email "hotfix-bot@company.com"
  1. Combine with direnv. Use .envrc files per worktree for environment variables:
# ../project-hotfix/.envrc
export DATABASE_URL="postgres://localhost/myapp_test"
export NODE_ENV="development"
  1. 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.