Story
What Is a Git Worktree and Why Does Each Agent Need Its Own?
I am the worktree. In one sentence: I am a separate, isolated working directory checked out from the same repository, on my own branch, so more than one contributor or agent can build, edit, and test code from that repository at the same time without stepping on each other's uncommitted changes.
What I actually do, in order
One repository has one shared history, but work doesn't happen in history -- it happens in a working directory, on disk, with files that can be half-edited at any moment. If two contributors or two agents share that same working directory and each is midway through a different change, one of them will eventually overwrite the other's uncommitted edits, or run a test suite against a file state that belongs to neither change. That's not a merge conflict -- merge conflicts are visible and git tells you about them. This is worse: silent overwrite of work nobody meant to touch.
I solve that by giving each stream of work its own floor to work on:
1. Check out onto a dedicated directory, not the shared clone. Instead of switching branches inside one directory and hoping nobody else needs it at the same moment, I create a distinct path on disk tied to one specific branch. 2. Share the underlying object store, not the working files. I'm not a full second clone -- commits, history, and objects are shared with the main repository. What's isolated is the working directory: the files on disk that a build or test run actually reads. 3. Bind one branch to one worktree. Git won't let the same branch be checked out in two worktrees at once, so there's no ambiguity about which directory owns which branch's in-progress state. 4. Stay independently buildable and testable. Whatever is running in my directory -- a build, a test suite, a dev server -- reads only my files, on my branch, unaffected by uncommitted changes happening in a sibling worktree. 5. Get removed cleanly when the branch is done. Once the work merges or is abandoned, I can be deleted without touching the shared history other worktrees depend on.
How I actually work here
In this operation, I'm the reason multiple agents can work on the same repository in parallel without a coordination meeting about who's allowed to touch the working directory right now. Each agent or task gets its own worktree, on its own branch, at a predictable path convention -- so nobody has to ask "is anyone else using this checkout" before starting work, because the answer is structurally always no.
I'm also the reason a reviewer or a second agent can inspect an in-progress change without disturbing it. Reading a diff from a worktree, or even running its tests, doesn't require checking out that branch in the shared clone and temporarily losing whatever was there before.
What I depend on: someone actually using me instead of reusing one shared checkout for convenience. I only prevent the collision if the collision-prone shortcut -- "just switch branches in the one directory we've got" -- is avoided in the first place. I'm a structural fix, not an enforced one; nothing stops a human or agent from ignoring me and working in the shared clone anyway.
Where I fail
This is the part that matters more than the part above, so I'm not going to bury it.
I don't protect the shared object store from contention. Multiple worktrees writing to the same underlying repository at once -- packing objects, writing refs -- can still contend with each other at the git level, especially under heavy concurrent load. Isolating working directories doesn't isolate every git-internal operation underneath them.
A ref that moves outside my worktree can surprise me. If something forces a branch update, deletes a ref, or rewrites history from a different worktree or the shared clone, I don't have my own private copy of history to fall back on -- I share that history, and a disruptive operation elsewhere can leave my checkout pointing at something unexpected.
I can't stop someone from bypassing me entirely. If a human or agent finds it faster to just switch branches in the main clone instead of creating a worktree, I offer no resistance -- I only help when I'm actually used.
I accumulate as clutter if nobody cleans me up. A worktree per branch per task adds up fast in a busy repository. Left unpruned, stale worktrees for long-merged or abandoned branches sit on disk indefinitely, and one of them being reused by mistake for new work is its own quiet source of confusion.
I don't resolve a merge conflict for you. I prevent uncommitted-file collisions between concurrent work. I don't make two people's changes to the same lines of the same file merge cleanly -- that's still a normal merge conflict, resolved the normal way, once both branches actually try to combine.
Tech-Tips
- Give every concurrent writer its own worktree, not a shared checkout. "We'll just take turns" is the exact failure mode a worktree exists to remove -- don't reintroduce it by convenience. - Use one consistent path convention (repo, then branch, in a dedicated parent folder) so nobody has to guess where a given task's worktree lives. - Prune worktrees for merged or abandoned branches on a schedule. Stale worktrees are easy to forget and easy to accidentally reuse. - Don't force-push or rewrite history on a branch someone else's worktree has checked out without telling them -- the shared object store means that disruption is visible on their side too. - Reviewers should read from the worktree or a git-native diff view, not check the branch out in their own primary clone. That's the whole point: inspecting a change shouldn't require displacing your own in-progress work.
Evidence: This piece describes the per-branch isolated-working-directory pattern used throughout our internal concurrent-agent coding operation -- shared object store, isolated working files, one-branch-per-worktree binding, and scheduled pruning of stale worktrees -- no vendor or specific product is named, per the moat-protection and STORY-FORMAT conventions. Evidence class: internal operating record and Owner attestation, 2026-08-25.