Git Worktrees & Parallel AI Agents

How two AI agents work on navbar and footer simultaneously without stepping on each other

A git worktree is a separate working directory attached to the same repository. Each worktree has its own set of files on disk and its own branch checked out — but they all share a single .git folder. This means commits appear instantly everywhere.

1 Physical Layout on Disk
~/project/                    ← Main repo (this is also a worktree)
├── .git/                     ← The ONE shared repository (contains all branches, commits)
├── src/
│   ├── layout.tsx           ← Shared components (both agents may touch this!)
│   ├── navbar.tsx
│   └── footer.tsx
├── package.json
└── styles.css              ← DANGER ZONE: both agents might edit this

~/project-navbar/              ← Worktree #1 for AI Agent 1
├── .git                     ← This is a FILE (not folder), points to ~/project/.git
├── src/
│   ├── navbar.tsx           ← Agent 1 editing this file
│   └── ...
└── [branch: feature/navbar]

~/project-footer/              ← Worktree #2 for AI Agent 2
├── .git                     ← This is a FILE (not folder), points to ~/project/.git
├── src/
│   ├── footer.tsx           ← Agent 2 editing this file
│   └── ...
└── [branch: feature/footer]
2 Timeline: Create → Work → Merge → Clean
flowchart TD
    subgraph SETUP["Setup"]
      S1["main worktree\n~/project/"] --> S2["create 2 worktrees"]
      S2 --> S3["~/project-navbar/\nbranch: feature/navbar"]
      S2 --> S4["~/project-footer/\nbranch: feature/footer"]
    end

    subgraph PARALLEL["Parallel Work (agents run at same time)"]
      S3 --> A1["Agent 1 edits\nsrc/navbar.tsx"]
      S4 --> A2["Agent 2 edits\nsrc/footer.tsx"]
      A1 --> A1c["Commits on\nfeature/navbar"]
      A2 --> A2c["Commits on\nfeature/footer"]
    end

    subgraph MERGE["Merge (from main worktree)"]
      A1c --> M1["git merge\nfeature/navbar"]
      A2c --> M2["git merge\nfeature/footer"]
      M1 --> M1r{"Conflict?"}
      M2 --> M2r{"Conflict?"}
    end

subgraph CONFLICT["Conflict Resolution"]
  M1r -->|"No conflicts\n(different files)"| OK1["Clean merge"]
  M2r -->|"No conflicts\n(different files)"| OK2["Clean merge"]
  M1r -->|"YES\n(styles.css edited by both)"| RESOLVE["Manually resolve\nmerge conflicts\nin shared files"]
  M2r -->|"YES\n(styles.css edited by both)"| RESOLVE
  RESOLVE --> FINAL["Commit merge\nresolution"]
end

    subgraph CLEANUP["Clean Up"]
      OK1 --> RM["git worktree remove\n~/project-navbar\n~/project-footer"]
      OK2 --> RM2["git branch -d\nfeature/navbar\nfeature/footer"]
    end

    style SETUP fill:#bd93f922,stroke:#bd93f9,stroke-width:1px
    style PARALLEL fill:#50fa7b22,stroke:#50fa7b,stroke-width:1px
    style MERGE fill:#8be9fd22,stroke:#8be9fd,stroke-width:1px
    style CONFLICT fill:#ffb86c22,stroke:#ffb86c,stroke-width:1px
    style CLEANUP fill:#6272a422,stroke:#6272a4,stroke-width:1px
    
Setup
Parallel work
Merge phase
Conflict zone
3 Conflict Scenario: When Both Agents Touch the Same File
flowchart LR
    subgraph BEFORE["Before"]
      ORIG["styles.css\n(original)"]
    end

    subgraph P1["Agent 1: Navbar"]
      N["styles.css\n.navbar { ... }\n.nav-links { ... }"]
    end

    subgraph P2["Agent 2: Footer"]
      F["styles.css\n.footer { ... }\n.social-icons { ... }"]
    end

    ORIG -->|"branch"| N
    ORIG -->|"branch"| F
    N -->|"merge first (clean)"| MERGED["styles.css\n.navbar { ... }\n.nav-links { ... }"]
    F -->|"merge second"| CONFLICT["CONFLICT!\nGit can't auto-merge\nbecause both changed\nsame file"]

    MERGED -->|"is the base now"| CONFLICT
    CONFLICT --> RESOLVE["You resolve manually:\nkeep nav styles + footer styles\nthen git add + commit"]

    style BEFORE fill:#6272a422,stroke:#6272a4,stroke-width:1px
    style P1 fill:#50fa7b22,stroke:#50fa7b,stroke-width:1px
    style P2 fill:#bd93f922,stroke:#bd93f9,stroke-width:1px
    style CONFLICT fill:#ff555522,stroke:#ff5555,stroke-width:2px
    style RESOLVE fill:#ffb86c22,stroke:#ffb86c,stroke-width:1px
    
4 The Commands
flowchart TD
    W1["1. CREATE worktrees\n(once, before agents start)"] -->|" "| C1
    W1 -->|" "| C2
    C1["git worktree add -b feature/navbar\n../project-navbar main"]
    C2["git worktree add -b feature/footer\n../project-footer main"]

    W2["2. AGENTS WORK\n(point each AI at its directory)"] -->|" "| D1
    W2 -->|" "| D2
    D1["AI Agent 1 → ~/project-navbar/\nworks on navbar.tsx\ncommits to feature/navbar"]
    D2["AI Agent 2 → ~/project-footer/\nworks on footer.tsx\ncommits to feature/footer"]

    W3["3. MERGE\n(from main project)"] -->|" "| M1_
    M1_["git merge feature/navbar"]
    M1_ -->|"clean (different files)"| M2_
    M2_["git merge feature/footer"]

    W4["4. IF CONFLICT\n(e.g. both edited styles.css)"] -->|" "| R1
    R1["git shows <<<<<<< markers\nmanually fix the file\ngit add styles.css\ngit merge --continue"]

    W5["5. CLEAN UP"] -->|" "| CL1
    CL1["git worktree remove\n../project-navbar\n../project-footer"]
    CL1 -->|" "| CL2
    CL2["git branch -d\nfeature/navbar\nfeature/footer"]

    style C1 fill:#8be9fd22,stroke:#8be9fd,stroke-width:1px
    style C2 fill:#8be9fd22,stroke:#8be9fd,stroke-width:1px
    style D1 fill:#50fa7b22,stroke:#50fa7b,stroke-width:1px
    style D2 fill:#bd93f922,stroke:#bd93f9,stroke-width:1px
    style M1_ fill:#ffb86c22,stroke:#ffb86c,stroke-width:1px
    style M2_ fill:#ffb86c22,stroke:#ffb86c,stroke-width:1px
    style R1 fill:#ff555522,stroke:#ff5555,stroke-width:1.5px
    style CL1 fill:#6272a422,stroke:#6272a4,stroke-width:1px
    style CL2 fill:#6272a422,stroke:#6272a4,stroke-width:1px
    
Key insight: Git worktrees don't magically prevent merge conflicts. They prevent working tree conflicts — two agents can never dirty the same file at the same time because they're in different directories. But if they both commit changes to styles.css, you still need to resolve the merge conflict after both are done.
Golden rule for AI coding with worktrees: Keep features separated by file boundaries whenever possible. If Agent 1 only touches navbar.tsx and Agent 2 only touches footer.tsx, merging is automatic. If they both edit styles.css, merge the first one, then let the second merge produce conflicts that you resolve.