· 7 min read ·

Git Worktrees Are the Right Primitive for Running Coding Agents in Parallel

Source: simonwillison

Simon Willison has been publishing a series of agentic engineering patterns, and his section on using Git with coding agents is worth reading carefully. The core discipline he describes is straightforward: start clean, use branches, review every diff. But once you start running agents in parallel, or orchestrating longer tasks without babysitting them, the workflow demands a bit more than branch hygiene. The underused primitive that makes all of this practical is git worktree.

The Clean Slate Is Not Optional

Before handing off to any coding agent, git status should show nothing. This matters more than it seems. If you start an agent session with uncommitted changes already in your working tree, you lose the ability to clearly distinguish what the agent did from what you already had in progress. The diff becomes a mixture of two intentions, and you cannot safely roll back to a known state.

This is not just a best practice for hygiene’s sake. It is the precondition for meaningful review. Every tool from Aider to Claude Code to Cursor’s agent mode makes assumptions about the baseline state of the files it is reading. A dirty working tree means the agent is reading context that does not match any committed state, and it will make decisions accordingly.

So the ritual is: check git status, commit or stash any open work, then start the session. Verify with git status again. Then proceed.

Branch Per Task, Without Exception

One agent session should produce one branch. If you allow an agent to work directly on main or on a branch you are also modifying by hand, you create a situation where the provenance of changes is ambiguous. When something breaks and you want to understand whether you introduced it or the agent did, you need that clean separation.

Aider enforces this discipline by design: it auto-commits after every accepted change, producing a commit-per-interaction history on whatever branch you start it on. The commit messages record the prompts that produced them, so the git history doubles as a decision log. This is more useful than it sounds. When a change turns out to be wrong, you can git log back through the session and trace exactly which prompt produced which edit.

Claude Code is less opinionated about commit frequency by default, but it is deeply git-aware: it reads git log, git diff, and git status as part of building its understanding of the codebase, and it respects .gitignore. Both approaches converge on the same pattern: agents should work on their own branch, and the output should be reviewable as a discrete unit before it goes anywhere permanent.

Git Worktrees: The Primitive You Probably Are Not Using

Branches handle isolation across time. Worktrees handle isolation across space, and that is what you need when running agents in parallel.

The git worktree add command creates a second (or third, or tenth) working directory attached to the same repository. Each worktree checks out a different branch, but all of them share the same .git object store. This means:

  • Multiple agents can work simultaneously without colliding on the working tree
  • You do not duplicate the full repository for each parallel session
  • Tearing down a failed session is git worktree remove, with no effect on any other session
# Create isolated working directories for two parallel agent tasks
git worktree add /tmp/agent-auth -b feature/auth
git worktree add /tmp/agent-payments -b feature/payments

# Run your agent in each directory independently
# When done, review and clean up
git diff main..feature/auth
git worktree remove /tmp/agent-auth

A full clone for isolation works but wastes disk space proportional to your object store size. Docker containers provide stronger process isolation but require more setup and do not interact natively with your local git tooling. Worktrees are the sweet spot: low overhead, real filesystem isolation, compatible with every agent tool that accepts a path to a git-tracked directory.

There is one caveat worth knowing: worktrees share the .git directory, including .git/COMMIT_EDITMSG and the ref store. Running concurrent git operations across worktrees can occasionally race on these shared resources. In practice this is rare, but if you are scripting agents at high parallelism, be aware the isolation is at the working tree level, not at the git metadata level.

Another edge case: git gc in the main repo operates across all worktrees’ references. This is almost always fine, but if a worktree is in a half-finished state and you run aggressive pruning, you could lose objects that the worktree’s in-progress work depends on. Run git gc after removing completed worktrees, not during active sessions.

Commit Granularity as an Audit Trail

There is a real trade-off in how frequently you commit during an agent session. Aider’s default of committing after every accepted change produces a fine-grained history that is easy to bisect and easy to roll back precisely. The downside is noise: a session that produces thirty small commits is harder to review as a whole than a session that produces three logical commits.

For exploratory work where you are not sure the agent will succeed, fine-grained commits are the right call. You want maximum rollback resolution. For deliberate, well-scoped tasks where you have high confidence in the approach, batching into logical commits before merging produces a cleaner record.

A pattern that threads this needle: let the agent accumulate all its changes, then review the full diff with git diff HEAD before committing anything. If the changes look correct, commit them yourself with a message that describes the intent, not just the mechanism. The agent-generated commit messages that Aider produces (which include the originating prompt) are useful during the session itself; a human-written summary is more useful six months later.

GitHub Copilot Workspace takes a different approach: the entire workflow is PR-mediated, with the agent always working on a branch and delivering output as a pull request. Every change is reviewable via the standard diff interface before it touches any shared branch. This is the right model for team workflows where multiple humans need to review and approve agent work.

Devin goes further: each session runs in an isolated cloud VM, and the only artifact that escapes back to your repository is a PR. You never have to manage worktrees or branches locally at all. The trade-off is that you lose direct visibility into the intermediate state of the session.

The Review Ritual

Before merging anything an agent produced, two commands:

git log --oneline main..HEAD    # How the agent structured its work
git diff main..HEAD             # Everything the agent changed

Agents routinely make changes outside the area you asked about. They refactor adjacent code, adjust imports in files you did not intend to touch, update configuration that seemed related to their task. Most of these changes are harmless or even correct. Some are not. The diff review catches both.

git diff at this stage is your primary verification tool. Not running the tests. Not reading the agent’s summary of what it did. The diff. Agents summarize their own work optimistically; the diff does not.

If the diff is large and you want to review it incrementally, git log --oneline main..HEAD followed by git show <commit> for each commit lets you reconstruct the sequence of decisions. With Aider-style auto-commits, each commit in that log corresponds to a specific prompt, making it relatively easy to trace the reasoning.

Pre-commit Hooks as Guardrails

Pre-commit hooks that run linters, formatters, and fast tests are useful in any workflow. With coding agents, they are particularly valuable because they catch whole categories of error before they enter the commit history at all. Agents generally respect hooks: if a hook rejects a commit, most agents will attempt to fix the failure and retry.

What you want to avoid is configuring agents to bypass hooks. Claude Code’s --dangerously-skip-permissions flag, for instance, can be used to disable hook execution in unattended pipelines. This makes sense in fully sandboxed CI environments where you control the entire execution context. It does not make sense in a shared repository where the hooks encode team agreements about code quality.

Treat your pre-commit hooks as the floor that agent output has to clear, just as you would for any contributor. The agent does not get special treatment because it is fast.

The Mental Model That Ties This Together

Git was designed for distributed, asynchronous collaboration between contributors who do not share context and who may make conflicting changes. A coding agent is exactly that kind of contributor: it has a bounded view of the codebase, it works asynchronously relative to your own understanding, and it will sometimes make changes that conflict with intentions you never expressed.

The git workflow discipline that Simon’s guide describes, and that tools like Aider have baked in from the beginning, is just applying the same patterns that work for distributed human collaboration. Branch isolation, meaningful commit history, mandatory review before merge. None of this is novel. What is different is the scale and frequency: agents produce more commits per hour than most humans, making the review step both more important and more cognitively demanding.

Worktrees lower the friction enough that running parallel sessions becomes practical without incurring the overhead of full repository duplication. The combination of worktrees for spatial isolation, branches for logical isolation, and disciplined diff review before merge is the workflow that makes agentic coding sustainable at more than toy scale.

Was this interesting?