AI Agents,  Console

Filesystem Parallelism for AI Agents

Git worktrees are evolving from a niche feature into an essential primitive for agent-assisted development. They provide filesystem-level parallelism, allowing agentic coding tools to operate concurrently on separate branches, builds, or refactors without sharing a mutable working directory.

Why Worktrees Matter Now

Modern AI Coding Assistants are becoming increasingly autonomous. They don’t just suggest completions; they execute multi-step plans, run terminal commands, modify multiple files, and orchestrate entire workflows.

This autonomy creates a new problem: mutable state collision.

When you have multiple AI agents (or one agent handling multiple tasks), they all want to:

  • Modify files in your working directory.
  • Run builds and tests.
  • Switch branches for different features.
  • Make commits.

Without isolation, these operations interfere with each other and with your own work.

Git worktrees solve this elegantly. Each worktree is a separate working directory linked to the same repository. Same Git history, same remotes, same branches but isolated filesystems.


Workspace Setup

Throughout this guide, I will use ~/projects as the workspace root. This is a clean, predictable location for managing multiple repos and their worktrees.

# Create your workspace
mkdir -p ~/projects
cd ~/projects

Clone the Repository

# Clone the main repository
git clone https://github.com/cli/cli.git
# Output:
# Cloning into 'cli'...
# remote: Enumerating objects: 79258, done.
# remote: Total 79258 (delta 0), reused 0 (delta 0), pack-reused 79258 (from 1)
# Receiving objects: 100% (79258/79258), 72.39 MiB | 6.05 MiB/s, done.
# Resolving deltas: 100% (54431/54431), done.

cd cli

# Verify you're in the right place
pwd
# Output: ~projects/cli

Worktree Fundamentals

Understanding Worktrees

A Git worktree is a linked working directory that shares the same .git data with your main repo. Think of it as a «view» into your repository at a specific branch.

# View current worktrees (every repo starts with one)
git worktree list

# Output:
# ~/projects/cli  cf53b76d7 [trunk]

Creating Your First Worktree

# Create a worktree for a new feature branch
git worktree add ../cli-feature-auth -b feature/auth
# Output:
# Preparing worktree (new branch 'feature/auth')
# HEAD is now at cf53b76d7 Merge pull request #12354 from cli/dependabot/github_actions/goreleaser/goreleaser-action-6.4.0

# Breakdown:
#   ../cli-feature-auth  → Directory path (sibling to main repo)
#   -b feature/auth       → Create and checkout new branch

Your filesystem now looks like:

~/projects/
├── cli/                  # Main worktree (trunk branch)
│   ├── .git/
│   ├── cmd/              # Main packages (gh executable)
│   ├── pkg/              # Command implementations
│   ├── internal/         # Internal packages
│   ├── api/              # GitHub API utilities
│   ├── go.mod            # Go module file
│   └── Makefile
└── cli-feature-auth/     # Feature worktree (feature/auth branch)
    ├── .git -> ../cli/.git/worktrees/cli-feature-auth
    ├── cmd/
    ├── pkg/
    ├── internal/
    ├── api/
    ├── go.mod
    └── Makefile

# Verify with: ls -la ~/projects/
# drwxr-xr-x  cli
# drwxr-xr-x  cli-feature-auth

Working with Existing Branches

# Create worktree from existing remote branch
git worktree add ../cli-bugfix-123 origin/bugfix/issue-123

# Create worktree from a specific commit
git worktree add ../cli-v2-review v2.0.0

Parallel Agent Sessions

The real power of worktrees emerges when running multiple AI coding sessions simultaneously.

Terminal-Based Parallel Sessions

Each terminal window operates in an isolated worktree:

Terminal 1 — Feature Development:

cd ~/projects/cli-feature-auth

# Check current branch and status
git status
# Output: On branch feature/auth
#         nothing to commit, working tree clean

git branch
# Output:
# * feature/auth
# + trunk

# Run your AI coding agent of choice in this isolated directory
# The agent operates on feature/auth branch without affecting trunk

Terminal 2 — Bug Fix:

cd ~/projects/cli-bugfix-123

# Different branch, different working directory
git log --oneline -5
git diff HEAD~1

# Run builds and tests independently
make test

Terminal 3 — Refactoring:

cd ~/projects/cli-refactor-utils

# Safe to run destructive operations
make build
make lint
git diff

Each worktree session has:

  • Its own file state.
  • Independent terminal context.
  • Isolated build artifacts.
  • No interference with other sessions.

Automated Worktree Creation for Agents

You can script worktree creation for agent workflows:

#!/bin/bash
# create-agent-worktree.sh

BRANCH_NAME=$1
WORKTREE_NAME="cli-${BRANCH_NAME}"

cd ~/projects/cli

# Create worktree with new branch
git worktree add "../${WORKTREE_NAME}" -b "$BRANCH_NAME"

# Initialize environment (Go project - dependencies fetched at build time)
cd "../${WORKTREE_NAME}"
make build

echo "Worktree ready at ~/projects/${WORKTREE_NAME}"
echo "Branch: ${BRANCH_NAME}"

Usage:

chmod +x create-agent-worktree.sh
./create-agent-worktree.sh feature/new-auth

Key Benefit: You continue working in your main workspace while agents operate in isolated worktrees.


Managing Work Across Worktrees

Tracking Active Worktrees

cd ~/projects/cli

# List all worktrees with their branches
git worktree list

# Output:
# ~/projects/cli               cf53b76d7 [trunk]
# ~/projects/cli-feature-auth  cf53b76d7 [feature/auth]
# ~/projects/cli-bugfix-123    cf53b76d7 [bugfix/issue-123]

Monitoring Changes Across Worktrees

# Check status in all worktrees from main repo
for wt in $(git worktree list --porcelain | grep worktree | cut -d' ' -f2); do
  echo "=== $wt ==="
  git -C "$wt" status --short
done

# Output (empty status means clean working tree):
# === ~projects/cli ===
# === ~projects/cli-feature-a ===
# === ~projects/cli-feature-auth ===
# === ~projects/cli-feature-b ===
# === ~projects/cli-feature-c ===

Branch Navigation

# See which branches are checked out where
git worktree list
# Output:
# ~projects/cli               cf53b76d7 [trunk]
# ~projects/cli-feature-auth  cf53b76d7 [feature/auth]

# View commits unique to a worktree branch
git log trunk..feature/auth --oneline
# Output: (empty if no commits have been made on the branch yet)

# View recent commits on trunk
git log --oneline -10
# Output:
# cf53b76d7 (HEAD -> trunk, origin/trunk, ...) Merge pull request #12354...
# 09e66252f chore(deps): bump goreleaser/goreleaser-action from 6.0.0 to 6.4.0
# c8335e3f5 Merge pull request #12315...
# ...

Practical Workflows

Workflow 1: Parallel Feature Development

cd ~/projects/cli

# Create worktrees for three parallel features
git worktree add ../cli-feature-a -b feature/user-dashboard
git worktree add ../cli-feature-b -b feature/notification-system
git worktree add ../cli-feature-c -b feature/analytics-module

# List all worktrees
git worktree list

# Output:
# ~/projects/cli               cf53b76d7 [trunk]
# ~/projects/cli-feature-a     cf53b76d7 [feature/user-dashboard]
# ~/projects/cli-feature-b     cf53b76d7 [feature/notification-system]
# ~/projects/cli-feature-c     cf53b76d7 [feature/analytics-module]

Now open three terminal tabs/windows for parallel work:

# Tab 1: User Dashboard
cd ~/projects/cli-feature-a
make build
git status

# Tab 2: Notification System
cd ~/projects/cli-feature-b
make build
git status

# Tab 3: Analytics Module
cd ~/projects/cli-feature-c
make build
git status

Each terminal now has an isolated environment ready for an AI agent or manual development.

Workflow 2: Code Review in Isolation

# Create worktree to review a PR without affecting your work
git fetch origin pull/42/head:pr-42
git worktree add ../cli-review-pr42 pr-42

cd ../cli-review-pr42

# Review the changes
git log --oneline -10
git diff trunk...pr-42 --stat
git diff trunk...pr-42

# Run tests on the PR code
make build
make test

# Check for issues
make lint

Workflow 3: Safe Refactoring in Isolation

# Create isolated worktree for major refactor
git worktree add ../cli-refactor-v2 -b refactor/v2-architecture

cd ../cli-refactor-v2

# Analyze current state before changes
find pkg/cmd -name "*.go" | head -20
# Output:
# pkg/cmd/codespace/ssh_test.go
# pkg/cmd/codespace/create.go
# pkg/cmd/codespace/select_test.go
# pkg/cmd/codespace/list.go
# ... (more files)

grep -r "authentication" internal/ --include="*.go" -l
# Output:
# internal/prompter/accessible_prompter_test.go
# internal/prompter/prompter.go
# internal/gh/gh.go
# internal/config/config.go
# internal/codespaces/rpc/invoker.go
# internal/run/stub.go

find . -name "*.go" | xargs wc -l | tail -1
# Output: 212847 total

# Initialize environment
make build

# Make changes safely - main workspace is unaffected
make build
make test

# Commit incrementally
git add -p
git commit -m "refactor: initial auth module restructure"

Workflow 4: CI/CD Testing Matrix

# Create worktrees for testing against different Go versions
git worktree add ../cli-test-go121 -b test/go-1.21
git worktree add ../cli-test-go122 -b test/go-1.22
git worktree add ../cli-test-go123 -b test/go-1.23

# In each worktree, run builds with different environments
cd ~/projects/cli-test-go121
go version  # Verify Go version
make build && make test

cd ~/projects/cli-test-go122
go version
make build && make test

# etc.

Worktree Lifecycle Management

Listing Worktrees

cd ~/projects/cli
git worktree list

# Verbose/machine-readable output
git worktree list --porcelain
# Output:
# worktree ~projects/cli
# HEAD cf53b76d71a8e26dd3f1e0106d6287e57592eaac
# branch refs/heads/trunk
#
# worktree ~projects/cli-feature-auth
# HEAD cf53b76d71a8e26dd3f1e0106d6287e57592eaac
# branch refs/heads/feature/auth

Removing Worktrees

# Remove a worktree (keeps the branch)
git worktree remove ../cli-feature-auth

# Force remove (if there are uncommitted changes)
git worktree remove --force ../cli-feature-auth

# Prune stale worktree references
git worktree prune

# Verify removal
git worktree list
# Output: ~projects/cli  cf53b76d7 [trunk]

# Note: Branches still exist after worktree removal
git branch
# Output:
#   feature/auth
# * trunk

# Delete branches when done
git branch -d feature/auth
# Output: Deleted branch feature/auth (was cf53b76d7).

Locking Worktrees

Prevent accidental removal during long-running operations:

# Lock a worktree
git worktree lock ../cli-feature-auth --reason "Agent running multi-day refactor"

# Verify the lock (shows in porcelain output)
git worktree list --porcelain | grep -A3 "cli-feature-auth"
# Output:
# worktree ~projects/cli-feature-auth
# HEAD cf53b76d71a8e26dd3f1e0106d6287e57592eaac
# branch refs/heads/feature/auth
# locked Agent running multi-day refactor

# Unlock when done
git worktree unlock ../cli-feature-auth

Unix Utilities for Worktree Management

Powerful shell commands for managing worktrees at scale:

Batch Operations Across Worktrees

# Run a command in all worktrees
for wt in $(git worktree list --porcelain | grep worktree | cut -d' ' -f2); do
  echo "=== Running in $wt ==="
  (cd "$wt" && make test)
done

# Example output header:
# === Running in ~projects/cli ===
# === Running in ~projects/cli-feature-auth ===
# (test output follows for each worktree)

Status Dashboard

# Create a worktree status report
git worktree list --porcelain | grep -E "worktree|branch" | paste - - | \
  awk '{print $2, $4}' | column -t

# Output:
# ~projects/cli               refs/heads/trunk
# ~projects/cli-feature-a     refs/heads/feature/user-dashboard
# ~projects/cli-feature-auth  refs/heads/feature/auth
# ~projects/cli-feature-b     refs/heads/feature/notification-system
# ~projects/cli-feature-c     refs/heads/feature/analytics-module

Automated Cleanup Script

#!/bin/bash
# cleanup-merged-worktrees.sh

cd ~/projects/cli

# Find worktrees with branches already merged to trunk
for wt in $(git worktree list --porcelain | grep worktree | cut -d' ' -f2); do
  branch=$(git -C "$wt" branch --show-current)
  if [ "$branch" != "trunk" ]; then
    # Check if branch is merged
    if git branch --merged trunk | grep -q "$branch"; then
      echo "Worktree $wt (branch: $branch) is merged and can be removed"
    fi
  fi
done

Diff Across Worktrees

# Compare changes between two worktrees
diff -rq ~/projects/cli-feature-a/src ~/projects/cli-feature-b/src

# Or using git
git diff feature/user-dashboard..feature/notification-system -- src/

Merging Worktree Changes

When your agent completes work in a worktree, integrate changes back:

Standard Merge

cd ~/projects/cli
git merge feature/auth

# Or with a squash for cleaner history
git merge --squash feature/auth
git commit -m "feat: add OAuth2 authentication"

Cherry-Pick Specific Commits

cd ~/projects/cli
git cherry-pick abc1234 def5678

Rebase for Linear History

cd ~/projects/cli-feature-auth
git rebase trunk

# Then merge as fast-forward
cd ~/projects/cli
git merge feature/auth

Troubleshooting

«Branch is already checked out»

# Error: fatal: 'feature/auth' is already checked out at '/path/to/worktree'

# Solution: Each branch can only be checked out in one worktree
git worktree list  # Find where it's checked out

Stale Worktree References

# If a worktree directory was deleted manually
git worktree prune

# Verify
git worktree list

Worktree Has Uncommitted Changes

# Option 1: Commit or stash in the worktree first
cd ~/projects/cli-feature-auth
git stash

# Option 2: Force remove (loses changes!)
git worktree remove --force ../cli-feature-auth

Identifying Which Worktree You’re In

# Show current worktree and branch
git rev-parse --show-toplevel
# Output: ~projects/cli-feature-auth

git branch --show-current
# Output: feature/auth

# Add to your shell prompt (bash/zsh)
# In ~/.bashrc or ~/.zshrc:
export PS1='\w ($(git branch --show-current 2>/dev/null)) $ '

Best Practices Summary

PracticeRationale
Use sibling directories../project-feature-x keeps worktrees organized alongside main repo
Name worktrees descriptivelycli-feature-auth is clearer than wt1
Lock long-running worktreesPrevents accidental removal during agent operations
Clean up finished worktreesgit worktree remove + git worktree prune
Use .gitignore for build artifactsKeep worktrees clean with proper ignore patterns
Commit frequently in worktreesSmall commits make it easier to cherry-pick or review
Script repetitive operationsAutomate worktree creation and environment setup

The Agentic Future

  • Isolated state: No file conflicts between agents.
  • Deterministic context: Each agent sees a consistent snapshot.
  • Safe concurrency: Parallel execution without coordination overhead.

As AI coding assistants become more capable—running for hours, making hundreds of file changes, executing complex multi-step plans—worktrees become not just useful, but essential.

They’re the filesystem primitive that makes agentic parallelism practical.


Quick Reference

# === WORKTREE CREATION ===
git worktree add ../path -b branch-name     # New branch
git worktree add ../path existing-branch    # Existing branch
git worktree add ../path HEAD~5             # From specific commit

# === WORKTREE MANAGEMENT ===
git worktree list                           # List all worktrees
git worktree list --porcelain               # Machine-readable output
git worktree remove ../path                 # Remove worktree (keeps branch)
git worktree remove --force ../path         # Force remove
git worktree prune                          # Clean stale references
git worktree lock ../path --reason "msg"    # Prevent removal
git worktree unlock ../path                 # Allow removal

# === NAVIGATION ===
cd ~/projects/cli-feature-x                # Enter worktree
git rev-parse --show-toplevel               # Show worktree root
git branch --show-current                   # Show current branch

# === CROSS-WORKTREE OPERATIONS ===
git -C ../cli-feature-a status             # Status in another worktree
# Output: On branch feature/user-dashboard
#         nothing to commit, working tree clean
git diff trunk..feature/auth                 # Compare branches
git log trunk..feature/auth --oneline        # Commits unique to branch (empty if no commits)

# === MERGING ===
git merge feature/auth                      # Standard merge
git merge --squash feature/auth             # Squash merge
git cherry-pick abc1234                     # Cherry-pick commit

Minor Caveats / Nitpicks

Not every AI tool needs/uses worktrees natively.

  • VS Code Copilot agents (background agents) do not automatically create worktrees. Plain Copilot Chat usually doesn’t.
  • Cursor does; many Claude Code users do manually.
  • In practice people also mention: Disk usage still grows (full working dirs × number of worktrees).
  • Dependency duplication (node_modules, vendor/, venv) can be painful on large projects.
  • IDEs sometimes get confused if you open many worktrees at once.
  • git worktree UX is still regarded as a bit raw → hence all the wrapper CLIs/tools that appeared in 2025.
  • Some very heavy build toolchains dislike multiple checkouts on the same machine (resource contention).

I am not saying «initialize every environment per worktree», but you should know the pattern isn’t zero-cost magic.


Walkthrough Progress Summary

This guide was validated through a complete hands-on walkthrough on January 24, 2026 using the GitHub CLI repository (cli/cli).

SectionCommands
✅ Workspace Setupmkdir -p ~/projects, git clone
✅ Worktree Fundamentalsgit worktree list, git worktree add
✅ Parallel Feature DevelopmentCreated 4 feature worktrees
✅ Worktree Lifecyclelock, unlock, remove, prune
✅ Status DashboardBatch status across worktrees
✅ Cross-worktree Operationsgit -C commands
✅ Safe Refactoring Workflowfind, grep, code analysis (212,847 lines of Go)
✅ Branch Navigationgit log, git diff between branches
✅ CleanupRemove worktrees + delete branches
⏭️ Build/Testmake build, make test

Commands Executed

# Workspace setup
mkdir -p ~/projects
cd ~/projects
git clone https://github.com/cli/cli.git

# Worktree creation
git worktree add ../cli-feature-auth -b feature/auth
git worktree add ../cli-feature-a -b feature/user-dashboard
git worktree add ../cli-feature-b -b feature/notification-system
git worktree add ../cli-feature-c -b feature/analytics-module
git worktree add ../cli-refactor-v2 -b refactor/v2-architecture

# Worktree management
git worktree list
git worktree list --porcelain
git worktree lock ../cli-feature-auth --reason "Agent running multi-day refactor"
git worktree unlock ../cli-feature-auth

# Cross-worktree operations
git -C ../cli-feature-a status
git log trunk..feature/auth --oneline
git rev-parse --show-toplevel
git branch --show-current

# Status dashboard
git worktree list --porcelain | grep -E "worktree|branch" | paste - - | awk '{print $2, $4}' | column -t
for wt in $(git worktree list --porcelain | grep worktree | cut -d' ' -f2); do echo "=== $wt ==="; git -C "$wt" status --short; done

# Code analysis in refactor worktree
find pkg/cmd -name "*.go" | head -20
grep -r "authentication" internal/ --include="*.go" -l
find . -name "*.go" | xargs wc -l | tail -1

# Cleanup
git worktree remove ../cli-feature-a
git worktree remove ../cli-feature-auth
git worktree remove ../cli-feature-b
git worktree remove ../cli-feature-c
git worktree remove ../cli-refactor-v2
git worktree prune
git branch -d feature/analytics-module feature/auth feature/notification-system feature/user-dashboard refactor/v2-architecture

Final State

~/projects/
├── cli/        [trunk] ← Clean main repo (cf53b76d7)
└── README.md

All worktrees removed, all feature branches deleted, repository returned to clean state.

Git worktrees have been around since Git 2.5, but their moment is now. In an era of agentic development, they’re the primitive that makes parallelism safe.


References