Git worktrees let you have multiple working directories from the same repository, but they can cause issues with locks, pruning, and branch management.

The Error

Managing worktrees:

bash
git worktree add ../feature-branch feature

You see:

bash
fatal: 'feature' is already checked out at '/path/to/main-worktree'
fatal: a branch is expected to be checked out

Or:

bash
git worktree prune
bash
fatal: cannot prune worktree: worktree is locked
fatal: cannot delete locked worktree

Or:

bash
git worktree list

Shows worktrees that don't exist: `` worktree /path/to/deleted-dir HEAD abc123 branch refs/heads/feature

Why Worktree Issues Occur

Common causes:

  • Branch checked out elsewhere - Same branch in multiple worktrees
  • Locked worktrees - Administrative lock prevents operations
  • Prune failures - Deleted worktrees not cleaned up
  • Missing worktree directories - Directory deleted without worktree command
  • Stale worktree metadata - .git/worktrees contains outdated entries
  • Dirty worktree - Uncommitted changes prevent worktree operations

Diagnosis Steps

List all worktrees: ``bash git worktree list

Shows: `` main /path/to/main abc1234 [main] feature /path/to/feature def5678 [feature] * (detached) /path/to/current ghi8901

Check worktree details: ``bash git worktree list --porcelain

Shows detailed metadata for each worktree.

Check locked worktrees: ``bash git worktree list --porcelain | grep -A1 locked

Check worktree metadata: ``bash ls -la .git/worktrees/

Verify worktree directory exists: ``bash for wt in $(git worktree list --porcelain | grep worktree | cut -d' ' -f2); do test -d "$wt" && echo "$wt exists" || echo "$wt MISSING" done

Solution 1: Fix Branch Already Checked Out

Cannot add worktree for branch that's checked out elsewhere:

bash
fatal: 'feature' is already checked out at '/path/to/main'

Option A: Use different branch: ``bash git worktree add ../new-feature new-feature-branch

Option B: Create new branch: ``bash git worktree add ../feature-work -b feature-v2

Option C: Detached HEAD worktree: ``bash git worktree add ../feature-detached abc1234

Option D: Switch main worktree first: ``bash # In main worktree git checkout main git worktree add ../feature feature

Solution 2: Remove Locked Worktree

Worktree with lock file cannot be removed:

bash
git worktree remove ../feature
bash
fatal: cannot remove a locked worktree

Check why locked: ``bash cat .git/worktrees/feature/locked

May contain reason or be empty.

Force removal: ``bash git worktree remove --force ../feature

Or remove lock manually: ``bash rm .git/worktrees/feature/locked git worktree remove ../feature

Solution 3: Prune Missing Worktrees

Worktrees deleted without git command need cleanup:

bash
rm -rf ../feature-worktree
git worktree list

Still shows deleted worktree.

Prune deleted worktrees: ``bash git worktree prune

Prune with verbose output: ``bash git worktree prune -v

Shows: `` Removing worktrees/feature: gone Removing worktrees/old-branch: gone

Prune locked worktrees: ``bash git worktree prune --force

Annotated pruning: ``bash git worktree prune -v --expire=30.days.ago

Solution 4: Fix Stale Worktree Metadata

If .git/worktrees contains outdated entries:

bash
ls .git/worktrees/

Manual cleanup: ```bash # Identify stale entries for wt in .git/worktrees/*; do wt_path=$(cat "$wt/gitdir" | head -1) test -d "$wt_path" && echo "$wt valid" || echo "$wt stale" done

# Remove stale entries for wt in .git/worktrees/*; do wt_path=$(cat "$wt/gitdir" | head -1) if [ ! -d "$wt_path" ]; then rm -rf "$wt" echo "Removed $wt" fi done ```

Solution 5: Fix Worktree with Dirty State

Cannot remove worktree with uncommitted changes:

bash
git worktree remove ../feature
bash
fatal: cannot remove a worktree with uncommitted changes

Option A: Commit or stash first (in that worktree): ``bash cd ../feature git stash push -m "saving before worktree removal" cd ../main git worktree remove ../feature

Option B: Force removal (loses uncommitted changes): ``bash git worktree remove --force ../feature

Solution 6: Repair Damaged Worktree

If worktree metadata is corrupted:

bash
git worktree repair

Output: `` Repair worktree links for /path/to/main Repair worktree links for /path/to/feature

Repair specific worktree: ``bash git worktree repair ../feature

Solution 7: Move Worktree

Relocate worktree properly:

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

If move fails due to lock: ``bash rm .git/worktrees/feature/locked git worktree move ../feature ../new-location

Solution 8: Lock Worktree for Protection

Prevent accidental removal:

bash
git worktree lock ../feature

Lock with reason: ``bash git worktree lock --reason "WIP on critical feature" ../feature

Unlock when ready: ``bash git worktree unlock ../feature

Solution 9: Create Worktree from Remote Branch

For branch not yet local:

bash
git fetch origin feature-branch
git worktree add ../feature feature-branch

Or: ``bash git worktree add ../feature origin/feature-branch

Verification

Verify worktree list is correct: ``bash git worktree list

Should show only existing worktrees.

Verify worktree works: ``bash cd ../feature git status git log --oneline -3

Verify no stale entries: ``bash ls .git/worktrees/

Should match output of git worktree list.

Verify branch operations work: ``bash cd ../main git checkout main cd ../feature git checkout feature

No "already checked out" errors.

Worktree Commands Reference

```bash # Create worktree git worktree add <path> [<branch>] git worktree add <path> -b <new-branch>

# List worktrees git worktree list git worktree list --porcelain

# Remove worktree git worktree remove <path> git worktree remove --force <path>

# Prune deleted worktrees git worktree prune git worktree prune -v git worktree prune --expire=<time>

# Lock/unlock git worktree lock <path> git worktree lock --reason "message" <path> git worktree unlock <path>

# Move worktree git worktree move <source> <destination>

# Repair worktree git worktree repair ```

Best Practices

Use descriptive worktree locations: ``bash git worktree add ../project-feature-auth feature-auth

Lock critical worktrees: ``bash git worktree lock --reason "Active development" ../feature

Regular pruning: ``bash git worktree prune -v

Add to maintenance routine.

Use separate branches for worktrees: ``bash git worktree add ../feature -b feature/my-feature main

Avoid checkout conflicts.

Clean up after done: ``bash cd ../feature git push origin feature cd ../main git worktree remove ../feature

Common Scenarios

Scenario: Working on two features simultaneously

```bash # Main worktree on main cd /path/to/main

# Create worktrees for each feature git worktree add ../feature-a feature-a git worktree add ../feature-b feature-b

# Work in parallel cd ../feature-a && vim src/a.js cd ../feature-b && vim src/b.js ```

Scenario: Quick bugfix while on feature branch

bash
# Create worktree from main for bugfix
git worktree add ../bugfix main
cd ../bugfix
vim src/fix.js
git commit -am "Fix bug"
git push
cd ../main
git worktree remove ../bugfix

Scenario: CI with worktree for testing

bash
# Create worktree for test environment
git worktree add ../test-env HEAD
cd ../test-env
npm install
npm test
cd ..
rm -rf test-env  # Remove directory
git worktree prune  # Clean metadata

Worktree Directory Structure

text
.git/
├── worktrees/
│   ├── feature/
│   │   ├── gitdir       # Path to worktree's .git file
│   │   ├── HEAD         # Current HEAD
│   │   ├── commondir    # Path to common .git
│   │   ├── locked       # Lock file (if locked)
│   │   └── index        # Worktree's index
│   └── another-worktree/
│       └── ...

Understanding this helps with manual repair.