ReadbackCourseReference · freeSign in
Reference6 sections · built in Lesson 09

AGENTS INPARALLEL

The setup for running several agents against one repository, what they share whether you meant it or not, and the two commands that tell you where they are going to collide.

The setup

One repository, one working tree, one index — however many branches exist. That is the problem: git switch rewrites the single working tree, and the index is shared, so two agents on one checkout corrupt each other’s staged state. A linked worktree gives each one its own (git-worktree).

CommandEffect
git worktree add -b agent-x ../wt-xNew directory, new branch, its own index and working tree. One per agent.
git worktree listEvery working tree, its checked-out commit and branch. The first line is the original clone.
git worktree remove ../wt-xCleans up. Does not delete the branch — the commits are all in the one object database.
git worktree pruneTidies the bookkeeping after a directory you deleted by hand.
cat ../wt-x/.gitOne line: gitdir: …. In a linked worktree .git is a file, not a directory — that is the whole mechanism.

What is shared, and what is not

The rule is one line of the docs: “all pseudo refs are per-worktree and all refs starting with refs/ are shared” (git-worktree, REFS). Everything below follows from it.

Shared across every worktreePrivate to each one
The object database — every commit, tree and blobThe working tree: the actual files on disk
Every branch, tag and remote-tracking refThe index, so staged changes cannot leak between agents
The config file, unless extensions.worktreeConfig is onHEAD, which is a pseudo ref — hence a different branch each
refs/stash — one stash stack for the whole repositoryrefs/bisect, refs/worktree, refs/rewritten — the named exceptions

Two consequences worth holding on to. A commit made in one worktree is instantly visible from another — no fetch, no push, because there is nothing to synchronise; both are reading one object database. Reviewing one agent’s work from another agent’s directory is a plain git log.

And the stash is shared, which surprises people: refs/stash starts with refs/, so two agents that both stash are writing to one stack, and a git stash pop in one directory can apply another agent’s work into your tree.

The branch lock

Git enforces the one rule that makes this safe: a branch can be checked out in at most one worktree. add “refuses to create a new worktree when <commit-ish> is a branch name and is already checked out by another worktree”, and switch refuses for the same reason:

fatal: 'agent-retry' is already used by worktree at '/tmp/l09/wt-retry'

Two agents cannot end up on one branch by accident. Overriding it takes --force, which is a thing you have to mean.

The lock is a property of one repository, not of a branch name — so it does not extend to people. Two separate clones can both sit on feature with no complaint at all, which is the ordinary state of any team and is why the guardrail that protects your agents from each other does nothing for your colleagues. Verified 2026-08-01.

The cheap screen

Two branches can only conflict where the sets of files they touched overlap. Compute each set and intersect the pairs. Each set is a three-dot diff — what that branch did since it left, not how it compares to main’s current tip:

comm -12 <(git diff --name-only main...agent-retry | sort) \
         <(git diff --name-only main...agent-timeout | sort)

Non-empty means escalate. <(…) is process substitution: bash and zsh have it, sh and dash do not.

Overlap is a warning, not a verdict

A shared file means a conflict is possible, not certain — two edits in one file merge silently unless their regions are adjacent. And an empty intersection only proves something if both branches have commits: an empty result because a branch is empty looks identical to one because two branches are disjoint.

The real check, without touching anything

git merge-tree --write-tree <a> <b> “performs a merge, but does not make any new commits and does not read from or write to either the working tree or index” (git-merge-tree). It is not an approximation — it “will use the same features as the ‘real’ git merge”, including rename detection and virtual merge bases. Safe to run in a loop while every agent is mid-task.

OutcomeWhat you get
Clean“For a successful merge, the output from git-merge-tree is simply one line” — the OID of the tree it would produce. Exit status 0.
ConflictedThat tree, then the stage table from lesson 08 for each conflicted path, then the informational CONFLICT lines. Exit status 1.
Could not runAny other exit status. So a supervision loop never has to parse the output at all.

Which makes the whole supervision loop two lines of shell over each pair of agent branches:

git merge-tree --write-tree "$a" "$b" >/dev/null 2>&1
case $? in 0) echo "$a $b clean";; 1) echo "$a $b COLLIDE";; *) echo "$a $b error";; esac

Note the ; rather than && — a conflicted merge-tree exits non-zero, and chaining would swallow the very thing you are reading. With --stdin the exit status is 0 either way, so do not use that form for this.

What you still have to duplicate

Git shares its own data and nothing else. Each worktree needs its own node_modules, its own build output and its own .env, because those live in the working tree and each worktree has a separate one. Untracked files do not travel between them either — usually what you want, occasionally a surprise.

DecisionThe honest answer
Worktrees or separate clones?Worktrees, unless you need different remotes or a submodule-heavy superproject — the docs call multiple checkout “still experimental” and submodule support “incomplete”.
How many agents?An empirical question, not a preference: run the file-intersection check over the branches they would work on. Heavily coupled code collides at two.
Which branch lands first?The smaller change. The second one has to resolve against the first, so you want the harder resolution to be the one with more context.
A4 or Letter
one ink, no chrome
Sources
  • git-worktreeREFS for the sharing rule, CONFIGURATION FILE for the shared config, DETAILS for the .git file, and BUGS for the honest limits.
  • git-merge-treeThe supervision command: output format, exit statuses, and the guarantee that it uses the same machinery as a real merge.
  • git-diff — the three-dot formWhy main...branch answers “what did this branch do since it left” and main..branch does not.
  • Git worktrees for parallel AI coding agents — UpsunA practitioner write-up of this exact pattern. Treat as a pattern source; verify mechanics against the docs above.