Git Worktrees for AI Development
Git Worktrees for AI Development
A Git worktree is a separate directory checked out from the same repository. You can have as many as you need, each on its own branch, all coexisting simultaneously on your filesystem.
Introduction
You are running Claude Code on a feature branch. The agent has been working for twenty minutes, it has read your codebase, built up context, and started making real progress on the authentication rewrite. Then a Slack message appears: production is down, someone needs a hotfix on main, and they need it now.
In the old workflow, you stash your changes, switch branches, lose everything your AI agent built up, fix the bug, push, switch back, and spend ten minutes getting the agent re-oriented to what it was doing. If you were running two agents simultaneously on the same directory, the situation is worse - both agents touching package.json, both generating edits to the same files, and the second writes silently, overwriting the first. No warning. No error. Just corrupted work you discover an hour later when tests fail in a way that makes no sense.
Git worktrees eliminate this entire class of problems. They are not a new invention - the feature has been in Git since version 2.5, released in 2015 - but the AI coding wave of 2025-2026 made them essential infrastructure. One .git directory, multiple working directories, each on its own branch, each invisible to the others. Each AI agent gets its own isolated workspace. The hotfix gets its own workspace. Nothing collides.
51% of professional developers now use AI tools daily, but only 17% of developers using AI agents say those tools have improved team collaboration. The gap between those two numbers is not a tooling problem. It is an infrastructure problem. Teams adopted AI agents without the workflow layer underneath. This guide is that workflow layer. By the end, you will know what worktrees are, how to set them up, how to run parallel AI agents inside them without chaos, and how to maintain them over the life of a project.
What Git Worktrees Actually Are
A standard Git repository has one working directory - the folder where your files live and where you edit code. To work on a different branch, you switch to it, which changes all the files in that directory to match the branch. If you have uncommitted work, you stash it first. If your AI agent is mid-task, you interrupt it.
Git worktrees break this constraint. A worktree is a separate directory checked out from the same repository. You can have as many as you need, each on its own branch, all coexisting simultaneously on your filesystem.
my-project/ โ main worktree (branch: main)
my-project-feat-auth/ โ linked worktree (branch: feat/auth)
my-project-feat-api/ โ linked worktree (branch: feat/api)
my-project-hotfix-login/ โ linked worktree (branch: hotfix/login)
All four directories share the same .git folder. They share history, objects, and commits. But each has its own checked-out files, its own index, and its own working state. An agent editing files in my-project-feat-auth/ cannot see or touch anything in my-project-feat-api/. They are physically separate directories that happen to share a git backend.
Why does this beat multiple clones?
The naive alternative to worktrees is cloning the repository twice and working in different clone directories. This works, but it has real costs: you duplicate the entire repository on disk, git history is not shared between clones, commits in one clone are not immediately visible in another, and there is no coordination between them at the git layer. With worktrees, you clone once. Every additional worktree adds only the cost of the checked-out files, not another copy of the full history.
The seven commands that cover everything you need to manage worktrees:
| Command | What It Does |
|---|---|
git worktree add -b <branch> <path> <base> |
Create a new worktree on a new branch |
git worktree add <path> <branch> |
Check out an existing branch into a new worktree |
git worktree list |
Show all active worktrees with their branches and commit hashes |
git worktree lock <worktree> |
Prevent a worktree from being pruned (useful while an agent is running) |
git worktree unlock <worktree> |
Release the lock |
git worktree remove <worktree> |
Delete a worktree cleanly (branch is preserved) |
git worktree prune |
Clean up metadata for worktrees that were manually deleted |
That is the full surface area. Everything else in this article is a workflow built on top of these seven commands.
Setting Up
Prerequisites: Git 2.5 or higher. Run git --version to check. Any modern system (macOS, Linux, Windows with WSL or Git Bash) ships with a version above 2.5.
Step 1: Starting From a Clean Repository
Worktrees work best when your main branch is clean. Commit or stash any in-progress work before creating your first worktree.
# Verify you have a clean working tree
git status
# If there is uncommitted work, commit it
git add . && git commit -m "checkpoint: work in progress"
Step 2: Creating Your First Worktree
# Create a new worktree at ../myapp-feat-auth on a new branch feat/auth
# Replace "myapp" with your project name and "feat/auth" with your branch name
git worktree add -b feat/auth ../myapp-feat-auth main
# Verify it was created
git worktree list
You should see output like this:
/home/user/myapp abc1234 [main]
/home/user/myapp-feat-auth abc1234 [feat/auth]
Both directories exist. Both contain the same files from the main branch. From this point, any changes you make in myapp-feat-auth/ stay on feat/auth and are completely isolated from main.
Step 3: Setting Up the Environment in the New Worktree
This is the step most tutorials skip. A worktree is a new working directory. It does not automatically have your .env file, your installed node_modules, or your Python virtual environment. You need to set those up explicitly.
cd ../myapp-feat-auth
# Copy environment files that are gitignored
# .env, .env.local, and similar files are not tracked in git --
# they will not appear in the new worktree automatically
cp ../myapp/.env .env
cp ../myapp/.env.local .env.local 2>/dev/null || true
# Node.js project: install dependencies
# Each worktree is an independent working directory --
# node_modules from the parent does not carry over
npm install
# Python project: create and activate a virtual environment
# python -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
Step 4: Verifying the Worktree Is Isolated
# From inside the new worktree
git branch
# Should show: * feat/auth
# Make a test change
echo "// test" >> test-isolation.js
git status
# Only shows the change in this worktree
# Switch to the main directory and verify it is unaffected
cd ../myapp
git status
# Clean -- the test-isolation.js change is invisible here
ls test-isolation.js 2>/dev/null || echo "Not here -- isolation confirmed"
That is all you need to get started. The worktree is live. Any agent you open in that directory operates only on feat/auth.
A Real-World Case Study
The clearest documented example of git worktrees used for AI-driven parallel development comes from the Microsoft Global Hackathon 2025. Tamir Dresher, an engineering lead, faced a problem that everyone building with AI agents eventually hits: too many features, too little time, and no way to work on more than one thing at once without constant context-switching.
Creating multiple clones of the repository was cumbersome. Switching branches destroyed the AI agent's context. Something had to change.
The solution was to use git worktrees to create what Dresher described as a virtual AI development team. Each feature got its own worktree. Each worktree got its own VS Code window. Each window ran its own AI agent. Dresher's role shifted from developer to tech lead: scoping tasks, reviewing output, guiding agents that got stuck, and merging finished work.
The setup looked like this:
myapp/ โ main window: coordination and reviews
myapp-feat-authentication/ โ Agent 1: implementing OAuth2 flow
myapp-feat-api-endpoints/ โ Agent 2: building REST endpoints
myapp-bugfix-login-crash/ โ Agent 3: fixing production bug
Each VS Code window was completely independent. Language servers, linters, and test runners run per window. The agents never touched each other's files. When Agent 1 finished, Dresher reviewed the diff, approved it, and opened a pull request (PR) from that branch - the same workflow as reviewing a PR from a human engineer.
Three concrete advantages Dresher documented from the hackathon:
- No context loss. Each AI agent maintained full context of its specific task. Switching between features meant switching VS Code windows, not branches, not stashes, not agent restarts. The agent's understanding of what it was building stayed intact.
- Different tools for different jobs. Because each window was independent, Dresher ran Roo in one window for rapid feature development and GitHub Copilot with Visual Studio in another for debugging complex issues. Mixing tools across tasks was trivial.
- Clean branch management. If a feature needed to be abandoned, closing the window and deleting the worktree took ten seconds. The other agents were unaffected.
The pattern that emerged from this hackathon is now a documented best practice across the AI coding community.
Running Parallel AI Agents With Worktrees
The mechanics of the full parallel workflow have four stages: set up the worktrees, give each agent its context, run the agents, and checkpoint regularly.
Stage 1: Scripting the Worktree Creation
Do not create worktrees manually each time. A script ensures every worktree gets the same setup - environment files, dependency installation, and a clean starting point.
Prerequisites: Git 2.5+, Bash (macOS/Linux/WSL)
How to run: Save as create-worktree.sh in your project root, run chmod +x create-worktree.sh, then ./create-worktree.sh feat/auth-redesign main.
#!/usr/bin/env bash
# create-worktree.sh
# Creates an isolated worktree for one AI agent task
# Usage: ./create-worktree.sh <branch-name> [base-branch]
# Example: ./create-worktree.sh feat/auth-redesign main
set -euo pipefail
BRANCH="${1:?Usage: $0 <branch-name> [base-branch]}"
BASE="${2:-main}"
REPO_ROOT="$(git rev-parse --show-toplevel)"
REPO_NAME="$(basename "$REPO_ROOT")"
# Replace slashes in branch name with dashes for directory naming
# feat/auth-redesign becomes feat-auth-redesign in the path
WORKTREE_PATH="${REPO_ROOT}/../${REPO_NAME}-${BRANCH//\//-}"
echo "Creating worktree for branch: $BRANCH"
echo "Base branch: $BASE"
echo "Worktree path: $WORKTREE_PATH"
# Fetch latest so the new branch starts from the current remote state
git fetch origin 2>/dev/null || echo "(no remote -- skipping fetch)"
# Create the worktree on a new branch from the base branch
# Falls back to checking out an existing branch if -b fails
git worktree add -b "$BRANCH" "$WORKTREE_PATH" "$BASE" 2>/dev/null || \
git worktree add "$WORKTREE_PATH" "$BRANCH"
# Copy non-tracked environment files into the worktree
# These are gitignored, so they do not carry over automatically
for f in .env .env.local .env.development .env.test; do
if [ -f "$REPO_ROOT/$f" ]; then
cp "$REPO_ROOT/$f" "$WORKTREE_PATH/$f"
echo "Copied $f"
fi
done
# Node.js: install dependencies in the new working directory
if [ -f "$WORKTREE_PATH/package.json" ]; then
echo "Installing Node dependencies..."
(cd "$WORKTREE_PATH" && npm install --silent 2>/dev/null || \
echo "(npm install skipped -- run it manually in the worktree)")
fi
# Python: remind the developer to set up their environment
if [ -f "$WORKTREE_PATH/requirements.txt" ] || [ -f "$WORKTREE_PATH/pyproject.toml" ]; then
echo "Python project detected."
echo "Run in the new worktree:"
echo " python -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt"
fi
echo ""
echo "Worktree ready. Open it in your IDE and start your agent:"
echo " cd $WORKTREE_PATH"
What this does: The script creates the worktree, copies gitignored environment files across (the most common setup failure), and runs dependency installation in the new directory. The ${BRANCH//\//-} substitution safely converts branch names like feat/auth into filesystem-friendly directory names like feat-auth. The fallback on line 23 handles the case where the branch already exists remotely.
Stage 2: Setting Up the AGENTS.md Context File
The single most important thing you can do to improve agent output is give each agent a clear, written context file. Peer-reviewed research at ICSE 2026 confirmed that incorporating architectural documentation into agent context produces measurable gains in functional correctness, architectural conformance, and code modularity.
The AGENTS.md file is how you deliver that context reliably, at scale, across every session. Create this file in your project root and commit it. Every agent reads it on session start. Different tools read different filenames - AGENTS.md (OpenAI Codex), CLAUDE.md (Claude Code), AGENTS.md (generic) - but the content matters more than the name.
# AGENTS.md
# Project context for AI coding agents
# Commit this to your repository root.
# Every agent that opens this project reads it first.
## Project Overview
Node.js/TypeScript REST API with a React frontend.
Stack: Node 20, Express 5, Prisma ORM, PostgreSQL, React 18, Vite.
## Build and Test Commands
npm run dev # start dev server on port 3000
npm run build # production build to dist/
npm run test # run all tests (Vitest)
npm run test:watch # watch mode
npm run lint # ESLint and Prettier check
npm run db:migrate # run pending Prisma migrations
npm run db:seed # seed development data
## Architecture
- API routes: src/routes/ one file per resource
- Business logic: src/services/ never in route handlers
- Database access: src/repositories/ never call Prisma directly from services
- Shared types: src/types/index.ts
## Conventions
Comments
No comments yet. Start the discussion.