Alex Leko
All content on this blog was fully or partially created using local AI (Apple MLX).

Working with Git worktrees

  • Git
  • Development
  • VersionControl
  • Programming
  • Workflow
  • Branches
  • Hotfix
  • IDE
  • SoftwareEngineering

git worktree checks out multiple branches into separate directories that share one repository's data. You can work on a feature, review a change, or prepare a hotfix without stashing your current changes or switching branches.

How it works

A standard Git repository has one working tree. Linked worktrees share the repository's objects and refs, while each has its own HEAD, index, and working files. You do not need to clone the repository again.

Core commands

Add a Worktree

# Create a worktree for an existing branch
git worktree add ../feature-login feature/login

# Create a worktree with a NEW branch
git worktree add -b hotfix/payment-bug ../hotfix-payment main

# Create a detached HEAD worktree (e.g. for a specific commit)
git worktree add --detach ../review-commit abc1234

List Worktrees

git worktree list

# Verbose output
git worktree list --porcelain

Example output:

/home/leko/my-repo          abc1234 [main]
/home/leko/feature-login    def5678 [feature/login]
/home/leko/hotfix-payment   ghi9012 [hotfix/payment-bug]

Remove a Worktree

# Remove a worktree (must not have uncommitted changes)
git worktree remove ../feature-login

# Force remove (discards uncommitted changes)
git worktree remove --force ../feature-login

# Prune stale worktree metadata (e.g. manually deleted directories)
git worktree prune

Move a Worktree

git worktree move ../feature-login ../new-location/feature-login

Lock/Unlock a Worktree

This is useful for worktrees on removable drives or network paths:

git worktree lock ../feature-login --reason "On external SSD"
git worktree unlock ../feature-login

Directory structure

One option is to keep linked worktrees beside the main repository:

~/projects/
├── my-repo/          ← main worktree
├── my-repo-feature/  ← linked worktree (feature branch)
├── my-repo-hotfix/   ← linked worktree (hotfix branch)
└── my-repo-review/   ← linked worktree (PR review)

A bare repository can serve as the root, with each worktree in a sibling directory:

git clone --bare git@github.com:user/repo.git my-repo.git
cd my-repo.git
git worktree add ../my-repo-main main
git worktree add ../my-repo-feature feature/login

Use cases

1. Hotfix While Mid-Feature

# You're deep in feature work — no need to stash!
git worktree add -b hotfix/critical-bug ../hotfix main
cd ../hotfix
# Fix, commit, push, then return to your feature

2. Running Tests in Parallel

git worktree add ../test-branch feature/new-algorithm
cd ../test-branch && npm test &   # runs in background
cd ../my-repo && continue working...

3. Reviewing a Pull Request Locally

git worktree add ../pr-review origin/pr-branch-name
cd ../pr-review
# Review, run, test — without touching your current branch

4. Building Multiple Versions Simultaneously

git worktree add ../build-v1 v1.0.0
git worktree add ../build-v2 v2.0.0
# Build both in parallel

Configuration and aliases

Add aliases like these to ~/.gitconfig:

[alias]
  wta  = worktree add
  wtl  = worktree list
  wtrm = worktree remove
  wtpr = worktree prune
  wtmv = worktree move

Usage:

git wta -b feature/dashboard ../dashboard main
git wtl

IDE integration

  • VS Code: Each worktree is a separate folder. Open one with code ../feature-login, or use the Workspace feature to group them.
  • JetBrains IDEs: Open each worktree as a separate project, or use the Directory Mappings in version control settings.

Practices

Practice Why
Use a consistent naming convention (repo-branchname) Easy to identify at a glance
Use bare repos as the root for large projects Cleaner structure, no "main" worktree confusion
Always prune after deleting directories manually Keeps metadata clean
Avoid sharing a branch across two worktrees Git will reject it — one branch per worktree
Use lock for worktrees on external/network paths Prevents accidental pruning
Add worktree paths to your shell's $CDPATH Fast navigation between trees

Limitations

  • One branch per worktree: You cannot check out the same branch in two worktrees simultaneously.
  • Submodules can behave unexpectedly across worktrees — test carefully.
  • Sparse checkouts are supported but require per-worktree configuration.
  • Some older Git hooks (pre-2.5) may not be worktree-aware.

Quick reference

git worktree add <path> <branch>        # Add worktree
git worktree add -b <new-branch> <path> # Add with new branch
git worktree list                        # List all worktrees
git worktree remove <path>              # Remove worktree
git worktree prune                       # Clean stale entries
git worktree move <old> <new>           # Move worktree
git worktree lock <path>                # Lock worktree