# Stop Making Your Agents Take Turns: Git Worktrees I hit this wall the first time I tried to be greedy with AI. I had one agent halfway through adding a feature, and a bug report came in that I wanted a *second* agent to chew on while the first one kept going. Two tasks, one machine, no reason I couldn't do both at once. The model's fast; I'm not. So I pointed a second session at the same folder and let it rip. Within about ninety seconds they were overwriting each other's edits to the same file, neither one aware the other existed. I'd turned two competent agents into one confused mess. The fix wasn't a better prompt or a smarter model. It was a piece of plumbing Git has shipped since 2015 that almost nobody talks about: **worktrees.** This is the last post in the first unit of [The Workflow](https://git.jpaul.io/justin/ai-workflow-course), my free course on the engineering scaffolding that makes AI-assisted coding actually work. In the [last post](https://git.jpaul.io/justin/ai-workflow-course) we covered branches: letting one agent try something risky on its own line of history with zero danger to `main`. Worktrees are the natural next step: the move that turns "I run an agent" into "I run *agents*." ## Where branches alone run out Branches give you *logical* isolation. Two lines of history that don't affect each other. Spin one up, let the agent do something wild, keep it or throw it away. Great. But there's a physical fact branches don't change: **a repo has exactly one working directory, and only one branch can be checked out in it at a time.** The files on disk are *the* files. When you `git switch other-branch`, Git rewrites those same files in place to match the other branch. One floor, and switching branches yanks it out and lays a different one down. That's fine when *you're* the only one standing on the floor. It falls apart the instant two things happen at once. Watch it break: ```bash # Agent A added a `wipe` command and committed it on its own branch: git switch -c feature/wipe # ...edits cli.py to add `wipe`... git commit -am "Add wipe command" # Agent B starts on a fresh branch off main, editing the SAME line # to add `remaining` and hasn't committed yet: git switch main git switch -c feature/remaining # ...edits cli.py, uncommitted... # You try to hop back to check on Agent A: git switch feature/wipe # error: Your local changes to the following files would be overwritten by checkout: # cli.py # Please commit your changes or stash them before you switch branches. ``` Git stops you, correctly: switching would silently destroy Agent B's in-progress work. But now you're stuck choosing between bad options: commit half-finished work just to get it out of the way, stash it and hope you remember to pop it (while Agent B keeps editing files that changed under it), or run both agents in the same folder and watch them clobber each other. The branch was never the problem. The single working directory is. You need two floors. ## What a worktree actually is `git worktree` gives you exactly that: **additional working directories attached to the same repository, each with its own checked-out branch.** One repo, many checkouts. ```bash cd ~/ai-workflow-course/tasks-app git worktree add ../tasks-app-remaining -b feature/remaining ``` That creates a brand-new folder, `~/ai-workflow-course/tasks-app-remaining`, with a full checkout of your project on a new branch. Your original folder is untouched, still on its own branch. You now have two real directories you can `cd` into, edit, and run independently: ``` ~/ai-workflow-course/ tasks-app/ ← the "main" worktree, on main tasks-app-remaining/ ← a "linked" worktree, on feature/remaining ``` Here's the part that makes it click. Both folders are backed by **one** repository. There's a single `.git`: one object store, one history, one set of branches. The linked worktree doesn't get a *copy* of the history; it gets its own copy of the *files* and a pointer back to the shared `.git`. The line I keep in my head: > **A clone copies the history. A worktree copies the working files and shares the history.** A clone is a second repository you sync with push/pull. A worktree is the *same* repository wearing two outfits. A commit you make in one worktree is instantly an object in the shared store. No pushing, no pulling; it's just *there*, because there's only one store. Think of it as one settled past, many present moments: this folder is "the project as of `feature/remaining`," that folder is "the project as of `main`," both writing to the same history. The whole command surface is small: ```bash git worktree add -b # new folder + new branch git worktree add # new folder, existing branch git worktree list # your map: every worktree + its branch git worktree remove # delete a worktree (must be clean) git worktree prune # forget worktrees whose folders you deleted by hand ``` And `git worktree list` is the map: ```bash $ git worktree list /home/you/ai-workflow-course/tasks-app a1b2c3d [main] /home/you/ai-workflow-course/tasks-app-wipe 7g8h9i0 [feature/wipe] /home/you/ai-workflow-course/tasks-app-remaining d4e5f6a [feature/remaining] ``` Three folders, one repo, three branches checked out at once. No stashing, no switching, no collisions. [insert a screenshot referencing two editor windows side by side, each open on a different worktree folder with an AI session running, here] ## Why this matters more for agents than for you A generic devops course would mention worktrees as a niche convenience for the human who hates stashing. For AI work they're closer to essential, and the reason is specific to how agents behave: - **An agent assumes its working directory is stable.** It reads files, reasons about them, and writes them back over a session that runs for many minutes. If a second agent (or you, switching branches) rewrites those files underneath it, the first agent is now operating on a reality that silently changed. That's the worst kind of bug, because nothing errors. The work just comes out wrong. A worktree pins each agent to a folder nobody else will touch. - **Parallelism is the whole point of cheap agents.** A feature here, a bugfix there, a doc update in a third. The constraint was never the model; it was that they'd trip over one repo. Worktrees remove the constraint. - **It keeps the output reviewable.** Each agent's work lands as its own branch with its own clean history, instead of a tangle of interleaved edits on one branch that no human could ever review. You don't reach for worktrees because you read about them. You reach for them the first time you watch two agents eat each other's homework. ## The hands-on version The course lab has you run two AI sessions *simultaneously* on the `tasks-app`: one adding a `wipe` command, one adding `remaining`, each in its own worktree. Set up: ```bash cd ~/ai-workflow-course/tasks-app git worktree add ../tasks-app-wipe -b feature/wipe git worktree add ../tasks-app-remaining -b feature/remaining git worktree list ``` Then you point one editor/AI session at `tasks-app-wipe` and a second at `tasks-app-remaining`, and let both work at the same time. While they run, you can prove the isolation from a third terminal: ```bash cd ~/ai-workflow-course/tasks-app-wipe && python cli.py add "from worktree A" && python cli.py list cd ~/ai-workflow-course/tasks-app-remaining && python cli.py add "from worktree B" && python cli.py list ``` Each `list` shows only its own task. Worktree A never sees "from worktree B." Each worktree even has its own `tasks.json` runtime state: separate files, separate state, while both agents work. Total isolation. When they're done, each commit lands on its own branch, and bringing both home is trivial because it's all already in one repo: ```bash cd ~/ai-workflow-course/tasks-app git switch main git merge feature/wipe git merge feature/remaining ``` No fetching, no syncing. The commits are already in the shared store, so the merges are local and instant. ## Where it breaks (because I like to be honest) Worktrees are sharp tools. The caveats I'd want you to know: - **You can't check out the same branch in two worktrees.** Git refuses (`fatal: 'main' is already checked out at ...`). That's a feature (it's exactly what stops two agents writing the same branch), but it surprises people. One branch, one worktree. - **Uncommitted work is *not* shared.** Only commits go to the shared store. Edits sitting modified-but-uncommitted in a worktree exist *only* in that folder, and `git worktree remove` on a dirty worktree refuses unless you `--force`, which throws that work away for good. Commit before you remove. - **Cleanup is a two-part chore.** Deleting a worktree folder with `rm -rf` does *not* tell Git it's gone; you'll have a stale entry in `git worktree list` until you run `git worktree prune`. Prefer `git worktree remove `, which does both. - **One shared object store means one shared fate.** Every linked worktree depends on the main repo's `.git`. Delete or move the main worktree and all of them break. Worktrees are *not* independent backups; they're one repository. - **They don't prevent merge conflicts, they defer them.** Two agents editing the same lines will still conflict *when you merge*. What worktrees buy you is that the conflict happens once, calmly, on your terms, not as two live agents corrupting each other's files in real time. Isolation during work; resolution after. ## That closes out Unit 1 That's the whole local foundation: version control as undo for the AI, getting the AI editing real files, committing its config, branches for safe experiments, and now worktrees so you can run more than one agent without a coordination nightmare. When "run two agents at once" feels like "open two folders" instead of "orchestrate a stash dance," you've got it. The model is the cheap, swappable part. The workflow around it is the skill that lasts, and this unit is the part of that workflow that lives entirely on your own machine. Next unit we get the work off this one machine: hosting, remotes, and reviewing code you didn't write. If you've run agents in parallel and hit something I didn't cover here, or found a sharp edge of your own, drop a comment. I read them, and the rough spots you hit are exactly what makes the course better.