Git Worktrees as an Orchestration Primitive: 5 Agents in Parallel on the Same Repo Without Merge Conflicts
Git worktrees solve a problem that no orchestration platform mentions: how to run multiple coding agents on the same repository without them overwriting each other's work. Full tutorial with bash aliases.
Fabiano Brito
CTO, Autenticare
git worktree allows N agents to work on the same repository in parallel, each in their own branch and working directory, without file-state conflicts. It's the orchestration primitive that was hiding in your git all along. Tutorial with bash aliases and automatic cleanup pattern included.
The classic problem of running multiple coding agents in parallel isn’t compute — it’s file state. When you launch 5 simultaneous agents on the same repository with git checkout, they all fight over the same git index, the same branches, the same working directory. The result is an indeterminate state that neither can reliably resolve.
The solution has been in git for years and most engineers have never used it in production: git worktree.
Addy Osmani documented this pattern in the context of coding agents. This post goes beyond the basic tutorial and covers what matters in production: resource management, automatic cleanup, and the aliases that make the workflow smooth.
What a worktree is, technically
A worktree is a separate working directory linked to the same git repository. Each worktree:
- Has its own working tree (files on disk)
- Is on a different branch (required — two worktrees cannot be on the same branch)
- Shares the same
.git/objects(commits, history, refs) - Is invisible to other worktrees during execution
This means each agent has full file-state isolation, but access to the same shared history. When it finishes, it pushes its branch and opens a PR — just like any human developer.
# Structure with 3 active worktrees
$ git worktree list
/Users/dev/my-repo abc1234 [main]
/Users/dev/my-repo-feat-a def5678 [auto/feat-a]
/Users/dev/my-repo-feat-b ghi9012 [auto/feat-b]
/Users/dev/my-repo-hotfix jkl3456 [auto/hotfix-login]
Each line is a separate directory, each running a different agent, with zero interference.
Why this matters for agent orchestration
The conventional approach to orchestrating coding agents uses one of these options:
- One repository per agent — high overhead, makes sharing the codebase hard
- Isolated branches in the same repo, with clone — works, but duplicates
.git/objectsand is slow - Sequential agents — eliminates the parallelism you want
Worktrees are the fourth option: parallel, same repo, no duplication, no conflict.
The overhead of creating a worktree is minimal — it’s essentially creating a directory with a HEAD pointing to a new branch. No copying of git objects. Spinning up a new agent in a worktree takes seconds, not minutes.
Worktrees turn git from a version control system into a context isolation system for agents. You're not running multiple checkouts — you're running multiple agents on the same repo with guaranteed state safety.
Setup: bash aliases for a smooth workflow
Add to your ~/.bashrc or ~/.zshrc:
# Create a worktree for an agent (auto naming convention)
wt-agent() {
local REPO_ROOT
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
if [[ -z "$REPO_ROOT" ]]; then
echo "Not inside a git repository." >&2
return 1
fi
local TASK="${1:?Usage: wt-agent <task-name>}"
local BRANCH="auto/${TASK}"
local WORKTREE="${REPO_ROOT%/*}/$(basename "$REPO_ROOT")-${TASK}"
git -C "$REPO_ROOT" worktree add "$WORKTREE" -b "$BRANCH"
echo "Worktree created: $WORKTREE (branch: $BRANCH)"
echo "cd $WORKTREE"
}
# List active worktrees with summary status
wt-list() {
git worktree list --porcelain | awk '
/^worktree / { wt=$2 }
/^branch / { br=$2 }
/^HEAD / { hd=substr($2,1,7) }
/^$/ { printf "%-50s %-30s %s\n", wt, br, hd }
'
}
# Remove worktree and delete local branch after merge
wt-clean() {
local TASK="${1:?Usage: wt-clean <task-name>}"
local REPO_ROOT
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
local WORKTREE="${REPO_ROOT%/*}/$(basename "$REPO_ROOT")-${TASK}"
local BRANCH="auto/${TASK}"
git worktree remove "$WORKTREE" --force
git branch -d "$BRANCH" 2>/dev/null || echo "Branch $BRANCH not found locally"
echo "Worktree and branch removed: $TASK"
}
# Launch a Claude Code agent in a worktree (requires claude CLI)
wt-claude() {
local TASK="${1:?Usage: wt-claude <task-name> [prompt]}"
local PROMPT="${2:-}"
local REPO_ROOT
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
local WORKTREE="${REPO_ROOT%/*}/$(basename "$REPO_ROOT")-${TASK}"
if [[ ! -d "$WORKTREE" ]]; then
wt-agent "$TASK"
fi
if [[ -n "$PROMPT" ]]; then
claude --cwd "$WORKTREE" --print "$PROMPT" &
echo "Agent launched in background (PID: $!)"
else
claude --cwd "$WORKTREE"
fi
}
With these aliases, the workflow to launch 5 parallel agents looks like this:
# Terminal 1 — refactoring agent
wt-claude "refactor-auth" "Refactor the authentication module to use the new JWT provider"
# Terminal 2 — test-writing agent
wt-claude "add-tests-payment" "Write unit tests for all handlers in the payment module"
# Terminal 3 — docs agent
wt-claude "update-api-docs" "Update API documentation with new endpoints added in #123"
# Terminal 4 — bug fix agent
wt-claude "fix-session-leak" "Fix the memory leak in session management (issue #456)"
# Terminal 5 — migration agent
wt-claude "migrate-db-schema" "Write migration to add composite index to the events table"
Each command launches an agent in the background, in an isolated worktree, on a separate branch. You monitor via wt-list.
Coordination pattern: the orchestrator agent
For interdependent tasks, use an orchestrator agent that dispatches subtasks to worker agents via worktrees:
#!/usr/bin/env bash
# orchestrate.sh — Simple orchestrator example
REPO_ROOT=$(git rev-parse --show-toplevel)
TASKS=("fix-auth-bug" "add-auth-tests" "update-auth-docs")
PIDS=()
# Launch agents in parallel
for TASK in "${TASKS[@]}"; do
WORKTREE="${REPO_ROOT%/*}/$(basename "$REPO_ROOT")-${TASK}"
git worktree add "$WORKTREE" -b "auto/${TASK}" 2>/dev/null
claude --cwd "$WORKTREE" --print \
"Your task: ${TASK}. When done, commit and push branch auto/${TASK}." \
&
PIDS+=($!)
echo "Agent ${TASK} launched (PID: ${PIDS[-1]})"
done
# Wait for all to finish
for PID in "${PIDS[@]}"; do
wait "$PID" && echo "Agent $PID done" || echo "Agent $PID failed"
done
echo "All agents done. Opening PRs:"
for TASK in "${TASKS[@]}"; do
gh pr create \
--head "auto/${TASK}" \
--title "auto: ${TASK}" \
--body "Generated by orchestrate.sh" \
2>/dev/null || echo "PR for ${TASK} already exists or failed"
done
The critical point here is separation of concerns: the orchestrator only dispatches and waits. Each worker has full autonomy within its worktree.
Limits and caveats
Worktrees solve the file-state problem, but don’t eliminate all coordination conflicts:
What worktrees do NOT solve:
- Two agents editing the same file on different branches still produce a merge conflict in the PR — worktrees isolate the working tree, not the intent of the change.
- Database locks or external resources (e.g., one agent running migrations while another tests against the same dev database) need external coordination.
- The limit on simultaneous worktrees depends on the filesystem — on NFS or slow volumes, each additional worktree has real I/O cost.
Best practices:
# Before creating worktrees, define explicit file partitioning
# Agent A: src/auth/**
# Agent B: src/payment/**
# Agent C: src/notifications/**
# → no overlap → no merge conflict
Task decomposition with explicit file partitioning reduces merge conflicts to near zero in most cases.
Automatic cleanup after merge
Forgotten worktrees accumulate orphaned directories. Set up a post-merge hook in the main repository:
# .git/hooks/post-merge (or via CI script)
#!/usr/bin/env bash
# Remove worktrees for branches that have been merged
MERGED_BRANCHES=$(git branch --merged main | grep "auto/" | tr -d ' ')
for BRANCH in $MERGED_BRANCHES; do
TASK="${BRANCH#auto/}"
REPO_ROOT=$(git rev-parse --show-toplevel)
WORKTREE="${REPO_ROOT%/*}/$(basename "$REPO_ROOT")-${TASK}"
if [[ -d "$WORKTREE" ]]; then
git worktree remove "$WORKTREE" --force
echo "Worktree removed: $WORKTREE"
fi
git branch -d "$BRANCH"
done
Implementing agent orchestration in your repository?
Autenticare designs multi-agent architectures with context isolation, branch coordination, and CI/CD pipeline integration. Talk to our team.
Related Posts
Agent Orchestra: Multi-Agent in Production Without Chaos
Agentic EngineeringWhen NOT to Use Autonomous Agents: 4 Anti-Patterns We've Seen Break in Production
Primary sources: git-worktree — official documentation · Addy Osmani — Code Agent Orchestra
