Skip to content

Worktree Conventions

This guide explains how to structure and manage Git worktrees for project work in the Arda workspace. Follow these conventions whether you are working alone or coordinating a multi-agent team.

Arda projects routinely span multiple repositories. When a feature touches both operations and common-module, for example, you need to make changes in two separate repositories simultaneously. Working directly in the main clone of each repository creates two problems:

  • Switching between branches in the main clone interrupts other in-flight work.
  • Two parallel agents writing to the same clone without coordination produce merge conflicts.

Git worktrees let you check out a separate branch into a separate directory while sharing the repository’s object store. You can have as many worktrees as you need — one per repository per task — each on its own branch. The main clone is always clean and ready for review or unrelated work.

Worktrees also make rollback clean. Abandoning a failed task is a single git worktree remove and git branch -D, with no residue in the main clone.

New projects use a grouped parent directory at the workspace root:

arda/
├── projects/
│ └── <project-name>-worktrees/ # parent directory for this project's worktrees
│ ├── <repo>-base/ # consolidation or multi-agent base worktree
│ ├── <repo>-<task>/ # task-specific worktree for a given repo
│ ├── documentation/ # worktree for documentation changes
│ └── workspace/ # worktree for skill or config changes

For example, a project called inventory with tasks registry and builder would produce:

arda/
├── projects/
│ └── inventory-worktrees/
│ ├── operations-registry/
│ ├── operations-builder/
│ ├── common-module-base/
│ └── documentation/

Earlier projects placed worktrees directly at the workspace root:

arda/
├── <project>-worktrees/
│ └── <task>/

You may encounter this layout in older projects. Do not create new projects using this pattern.

All branches include a GitHub username prefix so that branches are clearly attributed and can coexist without collision in the shared remote.

ContextPatternExample
Human-driven work<github-username>/<description>jmpicnic/add-bulk-import
Agent-driven work<github-username>-ag/<description>-<ticket-repo>-<ticket-number>jmpicnic-ag/fix-delete-management-782
Integration branch<github-username>/<project>/integrationjmpicnic/inventory/integration
Task branch (multi-agent)<github-username>/<project>/<task>jmpicnic/inventory/registry

When you are working alone on a feature that touches one repository, create one worktree:

Terminal window
# Create the parent directory
mkdir -p /Users/jmp/code/arda/projects/my-feature-worktrees
# Create the worktree on a new branch
git -C /Users/jmp/code/arda/operations worktree add \
/Users/jmp/code/arda/projects/my-feature-worktrees/operations \
-b jmpicnic/my-feature/operations

If the feature also touches documentation:

Terminal window
git -C /Users/jmp/code/arda/documentation worktree add \
/Users/jmp/code/arda/projects/my-feature-worktrees/documentation \
-b jmpicnic/my-feature/documentation

When multiple agents work in parallel on the same repository, add a base worktree for consolidation and a separate task worktree for each agent:

Terminal window
# Integration branch as the base
git -C /Users/jmp/code/arda/operations worktree add \
/Users/jmp/code/arda/projects/inventory-worktrees/operations-base \
-b jmpicnic/inventory/integration
# Task worktrees branched off integration
git -C /Users/jmp/code/arda/operations worktree add \
/Users/jmp/code/arda/projects/inventory-worktrees/operations-registry \
-b jmpicnic/inventory/registry
git -C /Users/jmp/code/arda/operations worktree add \
/Users/jmp/code/arda/projects/inventory-worktrees/operations-builder \
-b jmpicnic/inventory/builder

Each agent works exclusively in its assigned worktree. After all tasks complete, merge each task branch into the integration branch:

Terminal window
git -C /Users/jmp/code/arda/projects/inventory-worktrees/operations-base \
merge --no-ff jmpicnic/inventory/registry
git -C /Users/jmp/code/arda/projects/inventory-worktrees/operations-base \
merge --no-ff jmpicnic/inventory/builder

Then open a single PR from jmpicnic/inventory/integration to main.

The integration branch strategy isolates project work from main until all tasks are verified and ready to ship together.

main
└── jmpicnic/inventory/integration (integration branch, opened as one PR to main)
├── jmpicnic/inventory/registry (task branch, merged into integration)
└── jmpicnic/inventory/builder (task branch, merged into integration)

Steps:

  1. Create the integration branch off main before creating any task branches.
  2. Create task branches off the integration branch.
  3. Agents work independently on their task branches.
  4. When each task is complete, merge its branch into the integration branch. Resolve any conflicts here, not on main.
  5. When all tasks are merged and the integration branch passes CI, open one PR to main.
  6. After the PR is merged, clean up worktrees and task branches.

These rules apply to all project work, whether human-driven or agent-driven:

  • Always use absolute paths in agent tool calls. Agents inherit the spawning agent’s working directory, which may not match the worktree you intend. Relative paths silently operate on the wrong directory.
  • Never work directly in main clones for project work. Reserve main clones for reviewing, pulling updates, and unrelated ad-hoc changes.
  • Verify no uncommitted changes before removing a worktree. Run git -C <worktree-path> status first. Removing a worktree with uncommitted changes discards that work permanently.
  • Use workspace/instructions/claude/scripts/reset-worktrees.sh for phase-gate resets. This script verifies each worktree, resets branches to a known state, and re-applies the integration base. Do not reset worktrees manually when multiple task branches are involved.
  • Do not push task branches directly to main. All merges to main go through a PR. Task branches merge to the integration branch; the integration branch goes to main via PR.
  • Spell out worktree parent paths explicitly in permission allow-lists. The glob pattern *-worktrees/** does not reliably match hyphenated directory names in Claude Code’s permission system. List each worktree parent explicitly (e.g., inventory-worktrees/**).

When a project is complete and all PRs are merged, remove the worktrees and their branches.

1. Verify each worktree has no uncommitted changes:

Terminal window
git -C /Users/jmp/code/arda/projects/inventory-worktrees/operations-registry status
git -C /Users/jmp/code/arda/projects/inventory-worktrees/operations-builder status

2. Remove each worktree:

Terminal window
git -C /Users/jmp/code/arda/operations worktree remove \
/Users/jmp/code/arda/projects/inventory-worktrees/operations-registry
git -C /Users/jmp/code/arda/operations worktree remove \
/Users/jmp/code/arda/projects/inventory-worktrees/operations-builder
git -C /Users/jmp/code/arda/operations worktree remove \
/Users/jmp/code/arda/projects/inventory-worktrees/operations-base

3. Prune stale worktree metadata:

Terminal window
git -C /Users/jmp/code/arda/operations worktree prune

4. Delete the task branches (after confirming they are merged):

Terminal window
git -C /Users/jmp/code/arda/operations branch -d jmpicnic/inventory/registry
git -C /Users/jmp/code/arda/operations branch -d jmpicnic/inventory/builder
git -C /Users/jmp/code/arda/operations branch -d jmpicnic/inventory/integration

5. Remove the empty parent directory:

Terminal window
rmdir /Users/jmp/code/arda/projects/inventory-worktrees

Copyright: (c) Arda Systems 2025-2026, All rights reserved