Git Worktrees: The Complete Guide for 2026

Published February 12, 2026 · 22 min read

You are deep in a feature branch, files changed everywhere, build artifacts cached, tests running. Then Slack lights up: "Production bug, can you fix it now?" You reach for git stash, switch branches, lose your mental context, fix the bug, switch back, pop the stash, rebuild everything, and wonder if there is a better way. There is. It is called git worktree.

Git worktrees let you check out multiple branches of the same repository into separate directories simultaneously. No stashing, no cloning, no losing your place. Each worktree is a full working directory with its own staging area, but they all share the same Git history and object database. This guide covers everything you need to use worktrees effectively in real-world development.

Table of Contents

What Are Git Worktrees?

Every Git repository has a main working tree: the directory where you edit files, stage changes, and run builds. A worktree is an additional working tree linked to the same repository. It has its own checked-out branch, its own staging area, and its own set of files on disk, but it shares the same .git object database, reflog, and configuration as the main tree.

my-project/              <-- main worktree (feature/auth branch)
  ├── src/
  ├── package.json
  └── .git/

my-project-hotfix/       <-- linked worktree (hotfix/login branch)
  ├── src/
  ├── package.json
  └── .git              <-- file (not directory), points to main .git

Key things to understand about worktrees:

Worktrees were introduced in Git 2.5 (2015) and have been stable and production-ready for years. If you have Git 2.5 or later, you have worktree support.

git worktree add: Creating Working Trees

Basic Usage

The simplest form creates a new worktree and checks out an existing branch:

# Create a worktree for an existing branch
git worktree add ../my-project-hotfix hotfix/login-fix

# Output:
# Preparing worktree (checking out 'hotfix/login-fix')
# HEAD is now at a1b2c3d Fix login timeout handling

This creates the directory ../my-project-hotfix with the hotfix/login-fix branch checked out. You can now cd into it and work as if it were a normal clone.

Create a New Branch

Use -b to create a new branch and check it out in the worktree in one step:

# Create a new branch and worktree simultaneously
git worktree add -b hotfix/payment-bug ../payment-fix main

# This creates branch 'hotfix/payment-bug' starting from 'main'
# and checks it out in ../payment-fix

If you omit the start point, the new branch starts from HEAD:

# New branch from current HEAD
git worktree add -b experiment/new-parser ../parser-experiment

Detached HEAD Worktree

Sometimes you want a worktree at a specific commit without creating a branch. Use --detach:

# Check out a specific tag in a worktree
git worktree add --detach ../release-review v2.4.1

# Check out a specific commit
git worktree add --detach ../bisect-test abc1234

This is useful for reviewing tagged releases, running bisect in isolation, or comparing behavior at specific commits.

Tracking Remote Branches

# Fetch the latest remote branches first
git fetch origin

# Create a worktree tracking a remote branch
git worktree add ../review-pr origin/feature/new-dashboard

# Git automatically creates a local tracking branch
# Output:
# branch 'feature/new-dashboard' set up to track 'origin/feature/new-dashboard'
# Preparing worktree (new branch 'feature/new-dashboard')
# HEAD is now at e4f5g6h Add dashboard layout component

Choosing a Directory Layout

Where you put your worktrees matters for organization. Here are two popular patterns:

# Pattern 1: Sibling directories (simple, flat)
~/projects/my-app/               # main worktree
~/projects/my-app-hotfix/        # hotfix worktree
~/projects/my-app-review/        # review worktree

# Pattern 2: Parent directory with subdirectories (organized)
~/projects/my-app/main/          # main worktree (the repo)
~/projects/my-app/hotfix/        # hotfix worktree
~/projects/my-app/review/        # review worktree

Managing Worktrees: list, remove, prune

Listing Worktrees

git worktree list

# Output:
# /home/dev/projects/my-app           a1b2c3d [feature/auth]
# /home/dev/projects/my-app-hotfix    e4f5g6h [hotfix/login-fix]
# /home/dev/projects/my-app-review    i7j8k9l [feature/new-dashboard]

For scripting, use the porcelain format:

git worktree list --porcelain

# Output:
# worktree /home/dev/projects/my-app
# HEAD a1b2c3d4e5f6789012345678abcdef1234567890
# branch refs/heads/feature/auth
#
# worktree /home/dev/projects/my-app-hotfix
# HEAD e4f5g6h7i8j9012345678901234567890abcdef
# branch refs/heads/hotfix/login-fix

Removing a Worktree

When you are done with a worktree, remove it properly:

# Clean removal (fails if there are uncommitted changes)
git worktree remove ../my-app-hotfix

# Force removal (discards uncommitted changes)
git worktree remove --force ../my-app-hotfix

This deletes the directory and cleans up the internal worktree metadata. The branch itself is not deleted — only the working directory is removed.

Pruning Stale Worktrees

If a worktree directory is manually deleted (via rm -rf instead of git worktree remove), Git keeps stale references. Clean them up with:

# See what would be pruned (dry run)
git worktree prune --dry-run

# Output:
# Removing worktrees/my-app-hotfix: directory not found

# Actually prune
git worktree prune

Locking a Worktree

If a worktree is on a removable drive or network mount that might become unavailable, lock it to prevent accidental pruning:

# Lock a worktree
git worktree lock ../my-app-usb --reason "On external drive, may be unmounted"

# Check lock status
git worktree list  # locked worktrees show [locked]

# Unlock when the drive is reconnected
git worktree unlock ../my-app-usb

Parallel Development Workflows

Hotfix While on a Feature Branch

The classic use case. You are mid-feature and need to ship a fix immediately:

# You are on feature/auth with 20 changed files
# A production bug is reported

# Step 1: Create a hotfix worktree from main
git worktree add -b hotfix/critical-login-bug ../my-app-hotfix origin/main

# Step 2: Open the hotfix in a new terminal/editor window
cd ../my-app-hotfix

# Step 3: Fix the bug
vim src/auth/login.js
npm test
git add src/auth/login.js
git commit -m "Fix null pointer in login token validation"

# Step 4: Push the hotfix
git push -u origin hotfix/critical-login-bug

# Step 5: Go back to your feature branch (it never changed!)
cd ../my-app
# All your work is exactly as you left it

# Step 6: Clean up the hotfix worktree after it is merged
git worktree remove ../my-app-hotfix

Your feature branch was never touched. No stashing, no rebuilding, no lost context.

Code Review in a Separate Window

# Colleague opens a PR against feature/new-api
git fetch origin
git worktree add ../review-pr origin/feature/new-api

# Open in your editor, run tests, review the code
cd ../review-pr
npm install
npm test

# Leave review comments, then clean up
cd ../my-app
git worktree remove ../review-pr

Running Tests on Multiple Branches

# Compare test results between main and your branch
git worktree add --detach ../test-main origin/main

# Terminal 1: run tests on main
cd ../test-main && npm test

# Terminal 2: run tests on your feature branch
cd ../my-app && npm test

# Compare results side by side, then clean up
git worktree remove ../test-main

Long-Running Experiments

# Create an experiment without disturbing your main work
git worktree add -b experiment/rust-rewrite ../rust-experiment main

# Work on the experiment over days or weeks
# It shares the same history, so cherry-picking between them is easy

# When the experiment is done
cd ../my-app
git merge experiment/rust-rewrite
git worktree remove ../rust-experiment
git branch -d experiment/rust-rewrite

Using Worktrees with CI/CD

Parallel Build Testing

Worktrees are useful in CI pipelines where you need to build or test multiple branches without separate clones:

#!/bin/bash
# ci-parallel-test.sh - Test feature branch against main

REPO_DIR=$(pwd)
MAIN_WORKTREE="/tmp/ci-main-$$"

# Create a worktree for main
git worktree add "$MAIN_WORKTREE" origin/main

# Run tests in parallel
echo "Testing feature branch..."
npm test &
FEATURE_PID=$!

echo "Testing main branch..."
cd "$MAIN_WORKTREE"
npm install --silent
npm test &
MAIN_PID=$!

# Wait for both
wait $FEATURE_PID
FEATURE_EXIT=$?

wait $MAIN_PID
MAIN_EXIT=$?

# Clean up
cd "$REPO_DIR"
git worktree remove "$MAIN_WORKTREE"

# Report results
if [ $FEATURE_EXIT -eq 0 ] && [ $MAIN_EXIT -eq 0 ]; then
    echo "Both branches pass tests"
elif [ $FEATURE_EXIT -ne 0 ]; then
    echo "Feature branch tests FAILED"
    exit 1
fi

Documentation Deployment

#!/bin/bash
# deploy-docs.sh - Build docs from a specific branch without affecting the working tree

DOCS_WORKTREE="/tmp/docs-build-$$"

git worktree add --detach "$DOCS_WORKTREE" origin/main
cd "$DOCS_WORKTREE"

npm run build:docs
rsync -av dist/docs/ /var/www/docs/

cd -
git worktree remove "$DOCS_WORKTREE"

Git Bisect in Isolation

Bisecting in your main worktree disrupts your work. Use a separate worktree instead:

# Create a worktree for bisecting
git worktree add --detach ../bisect-workspace HEAD

cd ../bisect-workspace
git bisect start
git bisect bad HEAD
git bisect good v2.3.0

# Git checks out commits to test; your main tree is untouched
# Run your test at each step
npm test
git bisect good  # or git bisect bad

# When done
git bisect reset
cd ../my-app
git worktree remove ../bisect-workspace

Worktrees vs Git Stash vs Git Clone

All three let you work on multiple things, but they solve different problems:

Aspect Worktree Stash Clone
Disk spaceLow (shared objects)NoneHigh (full copy)
Parallel branchesYesNo (sequential)Yes
Shared historyYes (instant)Yes (same repo)No (needs fetch/push)
Build isolationYesNoYes
Setup timeSecondsInstantMinutes (network)
Context switchingNone (keep both open)Full (stash/pop)None (keep both open)
Best forHours-long parallel workQuick 5-minute fixesIndependent long-term forks

When Stash Is Better

Stash wins for quick, simple context switches where you will be back in minutes:

# Quick save, fix, and restore
git stash push -m "WIP: auth feature"
git checkout main
# ... quick fix ...
git checkout feature/auth
git stash pop

But stash becomes painful when: you have multiple stashes and lose track, you need to install dependencies after switching, or the fix takes longer than expected. See our Git Stash Complete Guide for more on when and how to use stash effectively.

When Clone Is Better

Cloning is better when you need complete independence: separate remotes, different Git config, or a long-lived fork that might diverge significantly. Worktrees share configuration, hooks, and remotes, which is usually what you want but occasionally a limitation.

Common Pitfalls and Best Practices

Pitfall 1: Same Branch in Two Worktrees

Problem: You try to check out main in a new worktree while it is already checked out in your main working directory.

$ git worktree add ../other main
fatal: 'main' is already checked out at '/home/dev/projects/my-app'

Solution: Create a new branch from the target, or use detached HEAD:

# Option 1: New branch from the same point
git worktree add -b hotfix/from-main ../other main

# Option 2: Detached HEAD
git worktree add --detach ../other main

Pitfall 2: Forgetting to Clean Up

Problem: Over time, stale worktree directories accumulate and their locked branches cannot be checked out elsewhere.

Solution: Make cleanup part of your workflow. After merging a branch, immediately remove its worktree:

# After the PR is merged
git worktree remove ../my-app-hotfix
git branch -d hotfix/login-fix

# Periodically check for orphaned worktrees
git worktree list
git worktree prune --dry-run

Pitfall 3: Node Modules and Build Artifacts

Problem: Each worktree needs its own node_modules, virtual environment, or build cache. Forgetting to install dependencies means broken builds.

Solution: Always run your install step after creating a new worktree:

# Create a shell function to automate this
gwt() {
    git worktree add -b "$1" "../$(basename $(pwd))-$1" "${2:-HEAD}" \
        && cd "../$(basename $(pwd))-$1" \
        && [ -f package.json ] && npm install \
        || [ -f requirements.txt ] && pip install -r requirements.txt
}

Pitfall 4: Shared Hooks Causing Confusion

Problem: Git hooks are shared across all worktrees (they live in the main .git/hooks). A pre-commit hook that references files by relative path may fail in a worktree with a different directory structure.

Solution: Use git rev-parse --show-toplevel in your hooks instead of assuming paths:

#!/bin/bash
# pre-commit hook that works in any worktree
ROOT=$(git rev-parse --show-toplevel)
npm --prefix "$ROOT" run lint-staged

For more on hooks, see our Git Hooks Complete Guide.

Pitfall 5: Stashes Are Shared

Problem: You stash something in one worktree and accidentally pop it in another.

Solution: Always use named stashes and check git stash list before popping:

# Name your stashes clearly
git stash push -m "worktree-hotfix: WIP on login fix"

# Check which stash to pop
git stash list
# stash@{0}: On hotfix/login-fix: worktree-hotfix: WIP on login fix

Best Practices Summary

Real-World Use Cases

Use Case 1: Reviewing Pull Requests Locally

Instead of stashing your work to review a colleague's PR:

# Fetch and create a worktree for the PR branch
git fetch origin pull/42/head:pr-42
git worktree add ../review-pr-42 pr-42

# Open in editor, run tests, leave feedback
cd ../review-pr-42
npm install && npm test

# Done reviewing
cd ../my-app
git worktree remove ../review-pr-42
git branch -D pr-42

Use Case 2: Comparing Behavior Across Versions

# Check out the last release and current main side by side
git worktree add --detach ../v2-release v2.0.0
git worktree add --detach ../v3-release v3.0.0

# Run both versions simultaneously on different ports
cd ../v2-release && PORT=3001 npm start &
cd ../v3-release && PORT=3002 npm start &

# Compare behavior in the browser, then clean up
kill %1 %2
git worktree remove ../v2-release
git worktree remove ../v3-release

Use Case 3: Maintaining Multiple Release Branches

# Keep active release branches in their own worktrees
git worktree add ../app-release-2.x release/2.x
git worktree add ../app-release-3.x release/3.x

# Backport a security fix to both
cd ../app-release-2.x
git cherry-pick abc1234
npm test && git push

cd ../app-release-3.x
git cherry-pick abc1234
npm test && git push

For more on cherry-picking across branches, see our Git Cherry-Pick Complete Guide.

Use Case 4: Worktree-Based Development Environment

Some developers keep a bare clone and use only worktrees:

# Clone as bare (no working directory)
git clone --bare git@github.com:org/project.git project.git

cd project.git

# Create worktrees for each task
git worktree add ../project-main main
git worktree add -b feature/auth ../project-auth main
git worktree add -b feature/dashboard ../project-dashboard main

# Each is an independent working directory
# The bare repo is just the shared .git database

This pattern keeps things clean: the bare repo never has uncommitted files, and each worktree is a focused workspace for a single task.

Frequently Asked Questions

What is a git worktree and how is it different from cloning?

A git worktree is an additional working directory linked to the same repository. Unlike cloning, which creates a completely independent copy of the entire repository including all Git objects, a worktree shares the same .git directory, commit history, and object database with the main working tree. This means worktrees use almost no extra disk space, branches stay in sync automatically, and any commit or stash you create is visible from every worktree. Use git worktree add to create one.

Can I have the same branch checked out in multiple worktrees?

No. Git prevents you from checking out the same branch in two worktrees simultaneously to avoid conflicting changes. If you try, Git will give an error saying the branch is already checked out. You can work around this by creating a new branch from the same commit with git worktree add -b new-branch ../path origin/branch, or by using a detached HEAD with git worktree add --detach ../path commit-hash.

How do I delete a git worktree?

Use git worktree remove <path> which deletes the directory and cleans up internal references in one command. If the worktree has uncommitted changes, add --force. If you manually deleted the directory with rm -rf, run git worktree prune to clean up the stale references. Always run git worktree list afterward to confirm the worktree was removed. Never delete the main worktree, only the additional ones you created.

Do worktrees share the same stash and staging area?

Worktrees share the same stash list because stash entries are stored in the shared .git directory. However, each worktree has its own independent staging area (index) and working directory. This means you can stage and commit different changes in each worktree without interference, but a git stash pop in one worktree can apply a stash that was created in another. Be mindful of this when using stash across worktrees.

When should I use git worktree instead of git stash?

Use git worktree when you need to work on two branches simultaneously for an extended period, such as developing a feature while also fixing a bug. Use git stash when you need a quick, temporary context switch that will last minutes, not hours. Worktrees let you keep both branches open in separate editor windows with their own build state, node_modules, and compiled output. Stash is simpler but forces you to stop, save, switch, fix, switch back, and restore, which is error-prone for longer tasks.

Do worktrees work with submodules and IDE integrations?

Worktrees have partial submodule support. Each worktree gets its own copy of submodule working directories, but you may need to run git submodule update --init in each new worktree. For IDE support, VS Code, JetBrains IDEs, and most modern editors handle worktrees well since each worktree is just a regular directory with source files. Open each worktree as a separate project window. Some IDE-specific files like .idea or .vscode should be gitignored to avoid conflicts between worktrees.

Continue Learning

This guide is part of our Git deep-dive series. Explore the related guides to build a complete understanding of Git workflows:

Related Tools

Git Diff Viewer
Visualize and compare diffs in the browser
Git Command Builder
Build Git commands with an interactive UI
Git Cheat Sheet
One-page quick reference for all Git commands
Regex Tester
Test regular expressions with live matching