Applied Intelligence
Module 6: Version Control with Agents

What Worktrees Are and Why They Matter

The isolation problem

Running multiple AI coding agents simultaneously against the same repository creates conflicts. The problems stack in ways you might not expect.

Consider a common scenario: two agents working in parallel, one refactoring authentication logic while another adds a new API endpoint. Both agents read the repository state at the start of their tasks. Both make changes. Both commit.

When Agent A modifies src/middleware/auth.ts, it has no awareness that Agent B is simultaneously editing src/routes/api.ts which imports from that file. Agent B's context includes the old version of the authentication module. Its changes assume an API that no longer exists. The resulting code compiles in neither agent's mental model and certainly not in reality.

This is file clobbering: agents overwriting each other's work because they share the same working directory. Three agents produce more conflicts than two. Five agents become unmanageable without isolation.

Beyond file conflicts

File clobbering is the obvious problem. The subtle problems cause more damage.

Context pollution across agents. Claude Code and Codex build understanding of the codebase as they work. When one agent makes changes, another agent's context becomes stale. The second agent makes decisions based on code that no longer exists, patterns that have changed, or assumptions that were invalidated by the first agent's work.

Research on multi-agent systems puts numbers to this: a 2% misalignment early in a reasoning chain can compound into a 40% failure rate by the end of extended interactions. When agents operate on shared mutable state without coordination, that initial misalignment is nearly guaranteed.

Build state interference. Modern development environments maintain substantial state beyond source files. node_modules directories, Python virtual environments, compiled artifacts, .env files, database migrations all change as agents work.

Agent A runs npm install to add a dependency. Agent B, working on a different feature, runs tests. Those tests may pass or fail depending on whether Agent A's installation completed, whether it modified shared lockfiles, whether the new dependency introduces conflicts. The outcome is non-deterministic.

Resource contention. Agents running tests compete for the same database. Agent A's test fixtures contaminate Agent B's assertions. Development servers fight over ports. Build processes race for CPU and memory. The "another git process seems to be running" error becomes common when multiple agents issue git commands simultaneously.

The underlying issue: shared mutable state. Every tool, dependency manager, and development process assumes a single developer working in sequence. Parallel agents violate that assumption.

Git worktrees as the solution

Git worktrees provide isolation without duplication.

A worktree is a separate working directory linked to the same repository. Each worktree has its own checked-out files, its own staging area, its own HEAD reference. But all worktrees share the same git objects, the same commit history, the same remote configuration.

# Create a new worktree for a feature branch
git worktree add ../project-auth-refactor auth-refactor

# Create a worktree with a new branch from main
git worktree add -b api-endpoint ../project-api-endpoint main

# List all worktrees
git worktree list

After running these commands, the directory structure looks like:

~/projects/
├── myproject/                  # main worktree
│   ├── .git/                   # actual git directory
│   ├── src/
│   └── ...
├── project-auth-refactor/      # linked worktree
│   ├── .git                    # file pointing to main .git
│   ├── src/
│   └── ...
└── project-api-endpoint/       # linked worktree
    ├── .git                    # file pointing to main .git
    ├── src/
    └── ...

Each worktree is a complete working directory. Running Claude Code in project-auth-refactor affects only that directory. Running Codex in project-api-endpoint affects only that directory. No file conflicts. No context pollution. No build state interference.

The shared git architecture

The efficiency of worktrees comes from what they share versus what they separate.

Shared across all worktrees:

ComponentLocationImplication
Object database.git/objects/Commits, blobs, trees stored once
Branch refs.git/refs/heads/Branch pointers visible everywhere
Tag refs.git/refs/tags/Tags visible everywhere
Remote configuration.git/configSame remotes for all worktrees
Hooks.git/hooks/Same hooks apply to all worktrees

Separate per worktree:

ComponentLocationImplication
Working directoryWorktree rootIndependent file state
Index (staging area).git/worktrees/<name>/indexIndependent staging
HEAD.git/worktrees/<name>/HEADDifferent branch per worktree
Checked-out filesWorktree rootIsolated modifications

This architecture means git fetch in any worktree updates remote refs for all of them. Commits made in one worktree are immediately visible in others (once pushed or via local refs). The repository remains cohesive while the working directories remain isolated.

Why not just clone multiple times?

The alternative to worktrees is multiple full clones. Both provide isolation. The differences matter.

Disk space. A repository with 30,000 files and substantial history might consume 1 GB per clone. Worktrees share the object database, requiring only the working files roughly 150 MB additional per worktree in this example. With five parallel workspaces, that's 5 GB versus 1.6 GB.

Creation speed. Cloning requires network transfer, receiving objects, resolving deltas. Creating a worktree requires only checking out files the objects already exist locally. On a repository that takes 90 seconds to clone, worktree creation completes in under 20 seconds.

Synchronization. Multiple clones are independent repositories. Fetching updates requires running git fetch in each clone separately. Worktrees share refs one fetch updates all. Branches created in one clone are not visible in another without explicit coordination. Worktrees see all local branches immediately.

The trade-off: dependencies. Working files are isolated, but worktrees do not share node_modules, virtual environments, or build artifacts. Each worktree needs its own dependency installation. For large JavaScript projects, this can mean significant disk usage and installation time.

The net calculation favors worktrees for ASD. The shared git database saves space and time. Dependency installation, while a cost, is a one-time setup per worktree and can be automated.

The one-branch constraint

Git enforces a rule: a branch can only be checked out in one worktree at a time.

Attempting to check out a branch that's active elsewhere:

git worktree add ../project-main main

Results in:

fatal: 'main' is already checked out at '/path/to/project'

This constraint prevents conflicting changes to the same branch from different directories. Without it, two worktrees could make incompatible modifications to the same branch, creating irreconcilable state.

Workarounds:

Create a new branch for each worktree:

git worktree add -b feature-auth ../project-auth main

Use a detached HEAD for temporary or throwaway work:

git worktree add -d ../project-temp HEAD

Track a remote branch (automatically creating local tracking branch):

git worktree add --track -b feature-xyz ../project-xyz origin/feature-xyz

The constraint shapes ASD workflow: each parallel agent session works on its own branch. Features merge back to main after completion. This aligns naturally with feature-branch development patterns most teams already use.

Cost-benefit at scale

The practical question: is the overhead of managing worktrees worth the isolation benefit?

incident.io, after adopting Claude Code with worktrees, reported running 4-5 agents simultaneously. A JavaScript editor that would have taken an estimated two hours was completed in 10 minutes. An API improvement costing $8 in Claude credits achieved 18% performance improvement 30 seconds saved on every request.

The cost differential between sequential and parallel agent work:

  • Sequential: One agent completes, next begins. Total time is sum of task times.
  • Parallel with conflicts: Agents compete, create merge conflicts, require manual resolution. Often slower than sequential.
  • Parallel with worktrees: Agents complete independently. Total time is longest single task plus merge time.

For two tasks each taking 30 minutes:

  • Sequential: 60 minutes
  • Parallel with worktrees: 30-35 minutes (including merge)

The worktree setup takes approximately 2 minutes. Dependency installation varies by project seconds for minimal dependencies, minutes for large JavaScript applications with bundlers.

Worktrees make sense when:

  • Agent tasks are independent (no overlapping file changes)
  • Tasks take longer than setup overhead
  • Developer time costs more than agent credits

For most enterprise development, all three conditions hold.

What this means in practice

Git worktrees make parallel agent work go from chaotic to manageable. The isolation they provide enables a different workflow entirely.

Without worktrees, running multiple agents requires careful coordination, staggered timing, and extensive conflict resolution. The cognitive overhead limits practical parallelism to one or two agents at most.

With worktrees, each agent operates in its own world. The developer monitors multiple sessions, reviews completed work, and merges results. The practical limit becomes review capacity, not conflict management.

Module 2 established that 3-5 parallel sessions typically outperform higher numbers due to merge complexity and context-switching overhead. That observation was made in the context of worktree-isolated sessions. Without isolation, even two parallel sessions become problematic.

The next section covers setting up worktrees specifically for agent isolation directory organization, environment configuration, and the practical mechanics of running isolated sessions.

On this page