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:
git worktree add ../feature-branch featureYou see:
fatal: 'feature' is already checked out at '/path/to/main-worktree'
fatal: a branch is expected to be checked outOr:
git worktree prunefatal: cannot prune worktree: worktree is locked
fatal: cannot delete locked worktreeOr:
git worktree listShows 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:
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:
git worktree remove ../featurefatal: cannot remove a locked worktreeCheck 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:
rm -rf ../feature-worktree
git worktree listStill 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:
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:
git worktree remove ../featurefatal: cannot remove a worktree with uncommitted changesOption 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:
git worktree repairOutput:
``
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:
git worktree move ../feature ../new-locationIf 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:
git worktree lock ../featureLock 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:
git fetch origin feature-branch
git worktree add ../feature feature-branchOr:
``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
# 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 ../bugfixScenario: CI with worktree for testing
# 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 metadataWorktree Directory Structure
.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.