We run more than one AI coding agent at a time. One's drafting a feature, another's fixing a bug, a third's writing marketing copy. For a while we ran them all in the same folder — the same git checkout — and it bit us.
Here's the failure, exactly. Two agents are working in repos/myproject. Agent A stages and commits its three files. Agent B, a few seconds later, runs git commit — and because git's staging index is shared across everything in one checkout, B's commit swept in A's staged files too, under B's message. Worse, the doc-rename A had queued landed inside B's unrelated commit. Nobody lost work — but the commit history no longer reflected what actually happened, and untangling it cost more than the feature did.
Why it happens
A git repository has one working directory and one index (the staging area) by default. Point two processes at it and they're editing the same desk. It's not an AI problem — two humans in the same checkout would collide the same way — but agents make it likely, because they commit constantly and don't notice another writer the way you'd notice a colleague reaching across your keyboard.
The reflex fix is "just be careful — commit only your own files by path." That works until it doesn't. The real fix is to stop sharing the desk.
The fix: one worktree per agent
git worktree lets one repository have several working directories, each on its own branch, each with its own index, all backed by the same .git. It's been in git since 2015 and it's perfect for this.
# from your worktrees folder, off the latest main:
git -C ../myproject worktree add "$PWD/feature-x" -b feature-x origin/main
cd feature-x
Now agent A lives in feature-x/, agent B in feature-y/. Separate directories, separate indexes. A's git commit physically cannot touch B's staged files. One folder, one agent, one branch — that's the whole rule, and it makes the collision impossible rather than merely unlikely.
The catch: your gitignored files aren't shared
There's one gotcha that surprises people. Worktrees share tracked, committed files through git — but gitignored, untracked files are per-directory. Your .env, your local scratch dir, your local data — they exist only in whichever checkout created them. A fresh worktree has no .env, so nothing runs.
You don't want to copy .env into every worktree (now you have N copies drifting apart). You want one canonical copy, symlinked in. We keep the canonical copies in the main checkout and symlink them into each worktree with a tiny script:
# inside the new worktree
for f in .env .local data; do
ln -s "$MAIN_REPO/$f" "$f"
done
Build state is the opposite — .venv, node_modules, build caches should stay local to each worktree, because different branches can have different dependencies. So: share config and data, never share the venv.
What we settled on
- One worktree per agent/feature, one session each. Never two agents in one directory.
- A
worktree-link.shscript that symlinks the shared gitignored state from the main checkout, and (with a--resetflag) fetches latest main, switches the worktree to a fresh branch, relinks, and installs deps — one command to start clean work. - The main checkout stays the trunk — we pull and integrate there, but don't run a building agent in it.
The cost is real but small: each worktree is a full checkout plus its own dependency install, so a handful of them is a few gigabytes, mostly virtualenvs. Cheap insurance against a corrupted history.
If you've started leaning on multiple agents and your git log has started looking strange, a shared checkout is the first thing to rule out. The rule that fixes it is small: one agent, one worktree, one branch.