Git Worktrees Break in Predictable Ways
Git worktrees give each AI agent its own working directory, its own branch, and its own staging area. That solves the obvious problem of two agents editing the same file at the same time. But worktrees share more than you think — the .git object database, the lock file system, and any tracked files that agents happen to modify in parallel. These shared surfaces create six distinct conflict types. Each one has a specific cause, a specific diagnostic, and a specific fix.
If you are setting up worktrees for the first time, start with the Git Worktree Multi-Agent Setup Guide. This article assumes your worktrees are already running and something has gone wrong.
1. Lock File Conflicts
What happens: Two agents in separate worktrees both run npm install (or yarn install, pnpm install). Each install modifies the lockfile — package-lock.json, yarn.lock, or pnpm-lock.yaml. Because lockfiles are tracked by git, the agents produce divergent lockfile versions on their respective branches. At merge time, you get a 5,000-line diff that no human can review.
Why it happens: Lockfiles are deterministic per install but not per branch. If agent A adds zod and agent B adds date-fns, both agents regenerate the entire lockfile tree. The resulting files differ on nearly every line, even though the actual dependency change is small.
Diagnosis:
# Check if lockfiles were modified in a worktree
cd ~/project-feature-auth
git diff --name-only main -- package-lock.json yarn.lock pnpm-lock.yaml
Fix:
# Option 1: Regenerate lockfile from the merged package.json
git checkout main
git merge feature-auth --no-commit
# Accept the package.json changes from both branches
# Then regenerate the lockfile
npm install # or yarn install / pnpm install
git add package-lock.json
git commit -m "merge feature-auth with regenerated lockfile"
# Option 2: Use npm's built-in merge driver
npx npm-merge-driver install -g
# Future merges auto-resolve package-lock.json conflicts
Prevention: Add a .gitattributes rule that tells git to use the npm merge driver for lockfiles. Alternatively, coordinate your agents so that only one branch installs new dependencies. The other agents work with the existing dependency set.
package-lock.json merge=npm-merge-driver
2. Git Index Lock Errors
What happens: An agent's git operation fails with:
fatal: Unable to create '/path/to/repo/.git/worktrees/feature-auth/index.lock': File exists.
The agent cannot stage files, commit, or run any write operation against the index.
Why it happens: Git creates an index.lock file before any write operation to prevent concurrent modifications. If the agent process crashes, the terminal is killed, or the system loses power during a git operation, the lock file is left behind. Each worktree has its own index lock at .git/worktrees/<name>/index.lock, so this only affects the specific worktree where the crash occurred.
Diagnosis:
# Check for stale lock files across all worktrees
find .git/worktrees -name "index.lock" -ls
# Check if any git process is actually running
ps aux | grep git
Fix:
# Only remove the lock if no git process is using it
rm .git/worktrees/feature-auth/index.lock
Prevention: Do not kill agent processes with kill -9 or by closing the terminal while a git operation is in progress. Use kill -15 (SIGTERM) instead, which gives the process time to clean up. If you are running Claude Code with --worktree, let the session end gracefully with /exit rather than force-closing the terminal.
3. Branch Checkout Conflicts
What happens: You try to create a worktree for a branch that is already checked out elsewhere:
fatal: 'feature-auth' is already checked out at '/Users/you/project-feature-auth'
Why it happens: Git enforces a one-worktree-per-branch rule. This is deliberate — if two worktrees had the same branch checked out, a commit in one would silently move the HEAD in the other, creating a corrupted state. The error is protection, not a bug.
Diagnosis:
# See which branches are checked out in which worktrees
git worktree list
/Users/you/project abc1234 [main]
/Users/you/project-feature-auth def5678 [feature-auth]
Fix:
# Option 1: Create a new branch based on the existing one
git worktree add ../project-auth-v2 -b feature-auth-v2 feature-auth
# Option 2: Remove the old worktree first if it's no longer needed
git worktree remove project-feature-auth
git worktree add ../project-feature-auth-new feature-auth
Prevention: Adopt a naming convention that ties worktree names to agent sessions. For example, feature-auth-agent1 and feature-auth-agent2. Claude Code's --worktree flag handles this automatically by generating unique worktree names.
4. Merge Conflicts at Integration Time
What happens: Agent A modified src/routes/index.ts on branch feature-auth. Agent B modified the same file on branch feature-api. When you merge both branches into main, git cannot auto-resolve the overlapping changes.
Why it happens: Worktrees isolate agents at the filesystem level, but they do not coordinate at the semantic level. Two agents working on different features will frequently touch shared files — route definitions, configuration files, barrel exports, type definitions, and database schemas. These are the "hotspot files" that every feature branch tends to modify.
Diagnosis:
# Before merging, check for overlap
git diff main...feature-auth --name-only > /tmp/auth-files.txt
git diff main...feature-api --name-only > /tmp/api-files.txt
comm -12 <(sort /tmp/auth-files.txt) <(sort /tmp/api-files.txt)
This shows files modified by both branches. If the list is long, expect painful conflicts.
Fix:
# Merge the first branch cleanly
git checkout main
git merge feature-auth
# Merge the second branch — conflicts will appear here
git merge feature-api
# Resolve conflicts manually, then:
git add .
git commit -m "merge feature-api, resolve conflicts with feature-auth"
For lockfile conflicts specifically during this merge, see the lockfile section above.
Prevention: This is the hardest conflict to prevent because it requires pre-merge planning. Three strategies work:
- Single-writer rule for hotspot files. Designate one agent as the owner of shared files like route definitions. Other agents add their routes through a separate file that gets imported.
- Merge early and often. Do not let branches diverge for days. Merge the first completed branch into main, then rebase the remaining branches before they finish.
- Additive-only changes. Instruct agents (via CLAUDE.md or prompts) to add new exports, new routes, and new types in separate files rather than modifying existing ones. Additions rarely conflict.
For a deeper look at coordinating multiple AI agents across worktrees, see the 2026 AI CLI Tools Complete Guide.
5. Stale Worktree References
What happens: git worktree list shows worktrees that no longer exist on disk. Git commands occasionally warn about orphaned worktree metadata.
Why it happens: If an agent session crashes, or you delete a worktree directory with rm -rf instead of git worktree remove, git retains the worktree's metadata in .git/worktrees/. The worktree appears in git worktree list but the directory is gone. This blocks creating a new worktree with the same name or branch.
Diagnosis:
# List all worktrees and check for "prunable" entries
git worktree list --porcelain
# Dry run — see what would be pruned
git worktree prune --dry-run
Fix:
# Remove all stale worktree references
git worktree prune
# Verify the cleanup
git worktree list
If a worktree's branch still has unmerged work, the branch itself is not affected by pruning. Pruning only removes the metadata link — commits remain in the repository.
Prevention: Always use git worktree remove <path> instead of rm -rf. If you are automating worktree lifecycle with scripts, add git worktree prune as a cleanup step. A simple alias helps:
# Add to .bashrc or .zshrc
alias gwtclean='git worktree prune --dry-run && git worktree prune && git worktree list'
6. Build Artifact Conflicts
What happens: Build commands in one worktree produce corrupted or stale output because they read cached artifacts generated by another worktree. This manifests as mysterious build failures, wrong bundle contents, or tests passing in one worktree but failing in another.
Why it happens: Build tools like Next.js (.next/), Vite (dist/), and TypeScript (tsconfig.tsbuildinfo) write to directories relative to the project root. If worktrees share a build cache — which happens when the cache directory is configured as an absolute path or when a monorepo tool stores caches in a shared location — agents contaminate each other's builds.
Additionally, node_modules/ is typically not shared between worktrees (each has its own copy), but if a worktree's node_modules was created by symlinking from the main worktree, dependency resolution can break when one agent modifies package.json.
Diagnosis:
# Check for shared cache directories
ls -la .next/ dist/ .turbo/ node_modules/.cache/
# Compare build fingerprints across worktrees
md5sum ../project-feature-auth/.next/BUILD_ID .next/BUILD_ID
Fix:
# Clear build caches in the affected worktree
rm -rf .next/ dist/ .turbo/ node_modules/.cache/ tsconfig.tsbuildinfo
npm run build
Prevention: Ensure build tools use worktree-local cache directories. For Next.js, this is the default behavior (.next/ is relative to the project root). For tools that support configurable cache paths, point them to a directory inside the worktree:
// turbo.json — cache is already worktree-local by default
// No changes needed for most tools
// For custom build scripts, use relative paths
// Bad: CACHE_DIR=/tmp/shared-build-cache
// Good: CACHE_DIR=./.build-cache
Add build output directories to .gitignore if they are not already there. Each worktree should build independently from source.
Monitoring Multiple Worktrees
Once you have three or more worktrees running, the overhead shifts from fixing conflicts to detecting them early. You need to see which agent is on which branch, whether any worktree has uncommitted changes, and which branches have diverged from main.
# Quick status across all worktrees
git worktree list | while read dir rest; do
echo "=== $dir ==="
git -C "$dir" status --short
done
Running this manually gets tedious. If you are managing multiple agent terminals, Termdock shows workspace-level git status across all your worktrees in a single view — each terminal pane displays its branch and change count, and you can drag to resize whichever agent needs attention.
Quick Reference: Conflict Cheat Sheet
| Conflict Type | Symptom | One-Line Fix |
|---|---|---|
| Lock file divergence | 5,000-line lockfile diff at merge | npm install after merging package.json |
| Index lock error | Unable to create index.lock | rm .git/worktrees/<name>/index.lock |
| Branch already checked out | fatal: already checked out | git worktree add -b new-branch-name |
| Merge conflict (shared file) | CONFLICT (content) on merge | Merge first branch, rebase second, resolve |
| Stale worktree | Ghost entries in worktree list | git worktree prune |
| Build cache contamination | Wrong build output, stale bundles | rm -rf .next/ dist/ and rebuild |
Each conflict type has a different root cause, but the common thread is shared state. Worktrees isolate the working directory, but they share the git database, tracked files across branches, and any absolute-path caches. Recognizing which layer of sharing caused your conflict is the fastest path to a fix.
For the complete setup guide on running parallel AI agents with worktrees, see Git Worktree Multi-Agent Setup. For a broader view of how AI CLI tools fit into modern development workflows, the 2026 AI CLI Tools Complete Guide covers the full landscape.
Ready to streamline your terminal workflow?
Multi-terminal drag-and-drop layout, workspace Git sync, built-in AI integration, AST code analysis — all in one app.