AIコーディングエージェントを一体から数体へ増やすと、作業時間は短くなる可能性があります。しかし、人数を増やしただけでは安全な並列開発にはなりません。同じファイルを同時に上書きする、頼んでいない場所まで変える、生成物を奪い合う、全員が「完了」と言うのに統合後のテストがない、といった事故が先に増えます。
この記事の結論は単純です。並列化の単位を「AIの数」ではなく、「独立した作業場所、ファイル所有、統合担当、採用証拠」の四点セットで決めます。 Gitのlinked worktreeは、そのうち作業場所を分ける強力な道具です。ただし、ファイル所有や統合判断まで自動で解決する道具ではありません。
本記事は2026年7月24日にGit、OpenAI、Anthropic、GitHubの公式文書を確認し、架空リポジトリを使った読み取り専用の例へ落とし込みました。ここに載せる作成・削除コマンドは仕組みを説明するための表示例であり、執筆時に実リポジトリでは実行していません。
この需要はどこから来ているのか
AIエージェントの並列実行は、研究上の構想だけではありません。OpenAIはCodexの各タスクが独立した環境で処理され、多数のタスクを並列に扱えると説明しています。Codexアプリの公式発表では、組み込みworktreeによって同じリポジトリに対する複数エージェントの作業を分離すると説明されています。AnthropicもClaude Codeでsubagent、agent team、worktreeセッションという異なる並列手段を比較し、worktreeをファイル編集の隔離に使っています。
一方、並列化が必要という事実と、安全に統合できるという事実は別です。GitHubの公式文書は、同じ行の変更や、一方の編集と他方の削除が競合を起こす典型例だと説明しています。AIが何体いても、最後に採用するコードは一つです。差分、競合解消、テスト、レビューの責任は消えません。
| 観測できる需要 | 公式資料で確認できること | 運用へ翻訳した課題 |
|---|---|---|
| 多数のエージェントを同時に動かしたい | OpenAIは並列タスクと分離された環境を案内している | 作業場所と成果の回収先を分ける |
| エージェント同士の編集衝突を避けたい | OpenAIとAnthropicはworktreeによる隔離を案内している | 同じ作業ツリーへ複数の書き手を入れない |
| 勝手な変更を止めたい | Claude Codeは権限と分離方式を案内している | 編集可能範囲と所有ファイルを先に固定する |
| 完了報告を確かめたい | Codexは端末ログとテスト出力による追跡可能な証拠を説明している | 自己申告ではなく差分と実行結果を採用条件にする |
| 最後の競合を安全に解く必要がある | GitHubは競合の種類と解消方法を案内している | 統合担当を一人に固定し、両方の意図を確認する |
需要の出発点となる三つのURLは、OpenAIのCodex初期発表、OpenAIのCodexアプリ発表、Anthropicの並列エージェント比較です。競合が実務上の問題になる根拠は、GitHubのマージ競合の説明で確認できます。
完了の証拠そのものを先に整えたい場合は、AIエージェントの完了報告を証拠で確かめるを併読してください。AIへ許す変更範囲はAIコーディングの変更権限マトリクス、作業環境の境界はAIコーディングエージェントのサンドボックス入門で補えます。
最初に分けるべき四つの選択肢
「別ブランチだから安全」「worktreeだから競合しない」という言い方は、半分だけ正しい説明です。同じ作業ツリー、別ブランチ、linked worktree、別cloneは、分離するものが違います。
| 方式 | 作業ファイル | HEADとindex | Gitオブジェクト | ローカルbranchとrefs | 主な用途 | 並列編集の評価 |
|---|---|---|---|---|---|---|
| 同じ作業ツリーを共有 | 同じ実ファイルを共有 | 同じものを共有 | 共有 | 共有 | 一人または読み取り中心 | 複数の書き手には不向き |
| 同じ作業ツリーで別ブランチへ切替 | 同じ場所を交互に入れ替える | 切替のたびに同じHEADとindexが変わる | 共有 | 共有 | 一人が作業を切り替える | 同時並列にはならない |
| linked worktree | worktreeごとに別の実ファイル | worktreeごとに分離 | 同じrepositoryのものを共有 | 多くのrefsと設定を共有 | 同じrepositoryの複数branchを同時に扱う | ファイル隔離に有効 |
| 別clone | cloneごとに別の実ファイル | cloneごとに分離 | 原則としてcloneごとに保持 | cloneごとに分離しremoteで同期 | 強い隔離、別端末、別環境 | 隔離は強いが同期負担が増える |
同じ作業ツリー
作業ツリーとは、実際にエディタやAIが読むファイル群です。二体のエージェントが同じフォルダを開き、同じsrc/app.tsを書けば、Git以前の段階で上書き競争になります。一体目が読み取った後、二体目が書き換え、一体目が古い内容を基に保存すれば、後から保存した側が相手の変更を消すことがあります。これはマージ競合として親切に止まるとは限りません。Gitに記録される前に変更が失われるからです。
同じ作業ツリーで安全に並列化できるのは、全員が読み取り専用で調査する場合や、一体だけが書き手で他がレビューする場合です。書き手が複数なら、作業場所を分けます。
同じ場所の別ブランチ
branchは作業フォルダの複製ではなく、履歴上の位置を示す名前です。一つの作業ツリーには、その時点で一つのHEADと一つのindexがあります。ブランチを切り替えれば表示されるファイルも切り替わりますが、二つのbranchを同じ作業ツリーに同時表示することはできません。
未保存または未commitの変更がある状態でbranchを切り替えると、Gitは変更を守るため切替を拒否することがあります。強制的な切替や破壊的な初期化で突破すると、今度は変更を失う危険があります。したがって「一つのフォルダでAIごとにbranch名だけ変える」は並列隔離ではありません。
linked worktree
Git公式のgit-worktree文書によると、一つのrepositoryはmain worktreeと複数のlinked worktreeを持てます。linked worktreeは別の作業ディレクトリを持ち、HEADやindexなどworktree固有のファイルを分けます。一方、Gitのオブジェクト、通常のrefs/heads/*、標準ではrepository設定などを共有します。
この構造により、AI-Aはfeature/search、AI-Bはfix/cacheのように別branchと別フォルダで作業できます。AI-Aの保存操作はAI-Bの実ファイルを直接上書きしません。ただし、両者が論理的に同じ行を変えれば、最後の統合時に競合します。worktreeが消すのは「作業中の物理的上書き」であり、「変更意図の競合」ではありません。
別clone
GitHubのrepositoryをcloneする説明は、cloneをリモートrepositoryのローカルコピーとして説明しています。別cloneでは作業ファイル、HEAD、index、local refs、設定、Gitオブジェクトの保管が原則として別になります。同じbranch名を両方でcheckoutすることもできます。
隔離が強い反面、片方のlocal commitやuntracked fileはもう片方から見えません。同期にはremoteへのfetchやpushなどの受け渡しが必要です。大量の依存ファイルやbuild cacheもcloneごとに増えやすく、ディスク消費と初期化時間が増えます。認証情報を各cloneへ複製する運用も避けるべきです。
worktreeで共有されるもの、分離されるもの
worktreeを安全に使うには、「別フォルダだから全部別」と思い込まないことが重要です。Gitのuser manualとrepository layoutは、worktree固有のmetadataと共通metadataを区別しています。
| 対象 | linked worktree間 | 実務上の意味 |
|---|---|---|
| 作業ディレクトリのファイル | 分離 | 保存時の直接上書きは避けられる |
HEAD | 分離 | worktreeごとに異なるbranchやdetached HEADを指せる |
index | 分離 | stage済みの内容はworktreeごとに持てる |
MERGE_HEADなど多くの疑似ref | 分離 | merge途中の状態は基本的にworktreeごと |
| object database | 共有 | commit、tree、blobを重複保存せず利用できる |
refs/heads/* | 共有 | branchの作成、更新、削除は他worktreeからも見える |
repositoryのconfig | 標準では共有 | 設定変更が全worktreeへ効く場合がある |
| worktree固有config | 拡張を有効にした場合に分離可能 | sparse checkoutなどを個別化できるが互換性確認が要る |
| remote情報 | 共有 | fetch後のremote-tracking refsは全worktreeから見える |
| untracked file | 分離 | main worktreeにある.envや素材は自動では現れない |
| ignored file | 分離 | build cache、依存フォルダ、秘密ファイルは各場所で別 |
| submoduleの作業ツリー | worktreeごとに注意が必要 | 初期化状態やcheckout先を別途確認する |
ここから二つの重要なルールが出ます。第一に、各worktreeのファイルが分かれていても、branch名やrepository設定を勝手に変更してよいわけではありません。第二に、main worktreeにしかないuntracked fileを前提にすると、新しいworktreeでは実行に失敗します。
branch、worktree、タスクの対応を一対一にする
安全な最小単位は「一つのタスク、一つのbranch、一つのworktree、一人の編集責任者」です。調査担当が複数いても、同じファイルを書ける責任者は一人にします。
| 管理対象 | 良い割当 | 避ける割当 | 理由 |
|---|---|---|---|
| タスク | 依存が少ない一件 | 「全部改善する」のような広すぎる仕事 | 完了条件と差分が曖昧になる |
| branch | 一タスクに一branch | 複数AIが同じbranchを別場所で更新 | branch先端の競争が起きる |
| worktree | 一書き手に一worktree | 同じ作業ツリーへ複数の書き手 | 保存時の上書きが起きる |
| ファイル | 所有者を一人に固定 | 同じ設定、schema、lockfileを全員が変更 | 統合時に意図を選べない |
| 生成物 | 出力先を分けるか統合担当だけが生成 | 全員が同じbundleや目次を再生成 | 内容が決定的でも時点差で衝突する |
| commit | タスク単位で意味を閉じる | 無関係な整形や依存更新を混ぜる | 採用と取消が難しくなる |
| 統合 | 一人の統合担当が順に採用 | 全員がmainへ同時にmerge | 競合判断と証拠が散る |
| 清掃 | 採用確認後に統合担当が行う | 作業者が未回収の場所を消す | untracked fileやcommitを失う |
AIへ仕事を渡す依頼文は、AIへの依頼状の書き方にある目的、対象、合格条件、禁止事項の四点へ、次の所有票を加えます。
架空タスクID: SEARCH-17
作業場所: D:\ai-lab\orion-search
担当branch: agent/search-filter
編集してよい場所:
- src/search/**
- tests/search/**
編集してはいけない場所:
- package-lock.json
- src/auth/**
- .github/**
生成物の出力先:
- artifacts/search-agent/**
統合担当:
- maintainer
完了証拠:
- 変更ファイル一覧
- diff検査
- 対象テストのコマンド、終了コード、生出力
これは架空例です。実在のbranchやworktreeを作る指示ではありません。重要なのは、ファイル所有をglobのような範囲で明示し、共通ファイルを統合担当へ寄せる点です。
同一ファイル所有を避けても残る衝突
「別ファイルを担当させたから安全」とも限りません。コードには依存関係があり、生成物や設定が複数の入力から作られるからです。
| 衝突の種類 | 例 | Gitが自動検出できるか | 予防策 |
|---|---|---|---|
| 同じ行の衝突 | 二つのbranchが同じ関数を変更 | merge時に検出しやすい | 同一ファイル所有者を一人にする |
| 編集と削除 | 一方がREADMEを編集、他方が削除 | merge時に競合になりやすい | 削除の決定者を固定する |
| 論理衝突 | 別ファイルだがAPIの前提が違う | 自動検出できない場合がある | interfaceと受入テストを先に固定する |
| 生成物衝突 | 二体が同じ目次やbundleを生成 | 差分になるが正解を選べない場合がある | 最後に統合担当だけが再生成する |
| lockfile衝突 | 別依存を追加し同じlockfileを更新 | text競合または大差分になる | 依存変更を一担当へ集約する |
| schema衝突 | 別機能が同じschemaへ項目追加 | 自動mergeできても意味が壊れる | schema所有者が両要求を統合する |
| cache衝突 | 同じcache directoryへ並列出力 | Git外で壊れることがある | worktree別cacheか一意な出力先を使う |
| port衝突 | 複数テストサーバーが同じportを使用 | Gitは検出しない | portを割り当てるか逐次実行する |
Gitが競合を出さなかったことは、正しさの証明ではありません。たとえばAI-AがAPIの引数を増やし、AI-Bが古い引数のまま別の呼び出し元を追加した場合、ファイルの行は競合しなくてもbuildやtestで失敗します。だから統合後の検証が必要です。
worktreeのlockは編集ロックではない
git worktree lockという名前から、ファイルを他のAIが編集できなくする機能だと誤解しやすい点に注意してください。Git公式文書では、lockはportable deviceやnetwork shareなど一時的に見えないworktreeがpruneされるのを防ぎ、移動や削除も防ぐための仕組みです。同じソースファイルへの同時編集を排他するlockではありません。
Claude Codeのagent team文書には、共有task listで複数のworkerが同じtaskを同時取得しないためのfile lockingも出てきます。これはタスク取得の競争を防ぐ仕組みで、Git worktree lockとは目的が違います。用語が同じでも、守る対象を分けて考えます。
| lockの種類 | 守る対象 | 防げること | 防げないこと |
|---|---|---|---|
| Git worktree lock | linked worktreeの管理情報と場所 | 自動prune、通常のmove、通常のremove | ソースファイルの同時編集、merge conflict |
| task claimのlock | 共有taskの取得状態 | 二体が同じtaskを同時取得する競争 | 別taskから同じファイルを編集すること |
| OSのfile lock | 開かれたファイルや資源 | 対応アプリ間の同時書込 | Git履歴上の論理競合 |
| 運用上の所有票 | 人またはAIの担当範囲 | 勝手な編集を検品で発見しやすくする | 技術的な強制力がない場合の違反 |
したがって、技術的な隔離と運用上の所有を重ねます。worktreeで物理的に分け、依頼票で編集範囲を決め、差分検査で違反を検出します。
架空repositoryで行う安全な読み取り
次はD:\ai-lab\架空オリオンという存在しない説明用repositoryを想定した、読み取り中心の例です。branchやworktreeの作成、削除、merge、commit、pushは含みません。PowerShellでは日本語や空白を含むpathを文字列として扱い、-LiteralPathを使うとwildcard解釈を避けられます。
Set-Location -LiteralPath 'D:\ai-lab\架空オリオン'
git rev-parse --show-toplevel
git rev-parse --git-dir
git rev-parse --git-common-dir
git branch --show-current
git worktree list --porcelain
git -c core.quotepath=false status --porcelain=v2 --branch
git diff --name-status
git diff --cached --name-status
git ls-files --others --exclude-standard
git submodule status --recursive
読み方は次の通りです。
| 読み取り | 確認すること | 異常の例 |
|---|---|---|
rev-parse --show-toplevel | 本当に対象repository内にいるか | 想定外の親repositoryを指す |
rev-parse --git-dir | このworktree固有のGit管理場所 | mainの.gitと異なるlinked metadataを指す |
rev-parse --git-common-dir | worktree間で共有するGit管理場所 | 想定外のrepositoryへつながっている |
branch --show-current | 現在のbranch | 空ならdetached HEADの可能性 |
worktree list --porcelain | worktree、HEAD、branch、lock、prunable | 同じ目的の古いworktreeが残る |
status --porcelain=v2 --branch | branch状態と変更状態 | 所有外ファイルの変更、未追跡ファイル |
diff --name-status | 未stageの変更ファイル | 依頼外の変更や削除 |
diff --cached --name-status | stage済みの変更ファイル | 無関係なファイルが混入 |
ls-files --others --exclude-standard | ignoreされていないuntracked file | 成果物が未追跡のまま回収されていない |
submodule status --recursive | submoduleの記録commitと状態 | 未初期化、別commit、競合 |
--porcelainは機械処理向けの安定した形式です。pathには改行など特殊文字も入り得るため、実際の自動処理ではGit公式文書が案内する-zも検討します。ただし、NUL区切りをPowerShellの単純な行処理へ渡すと扱いを誤ることがあるため、parser側も対応させます。
説明用の作成例と、実行してはいけない失敗例
次のコマンドは公式構文を理解するための説明用です。この執筆では実行していません。
# 説明用: 新しいbranchとlinked worktreeを作る一般形
git worktree add -b agent/search 'D:\ai-lab\orion-search' main
# 説明用: worktree一覧を読む
git worktree list --porcelain
# 説明用: cleanなlinked worktreeを通常手順で外す一般形
git worktree remove 'D:\ai-lab\orion-search'
失敗例は、次のような強制操作です。
# 失敗例: 変更の有無を確認せずforceで外す
git worktree remove --force 'D:\ai-lab\orion-search'
# 失敗例: worktreeのfolderをExplorerから先に手動削除する
# 失敗例: 別worktreeでcheckout中のbranchをforceで使い回す
# 失敗例: 複数AIへ同じ出力folderと同じlockfileを所有させる
remove --forceは、未commit変更やuntracked fileを失う可能性があります。Git公式文書では、通常のremoveはtracked変更やuntracked fileがあるunclean worktreeを拒否し、forceが必要になると説明しています。拒否は邪魔ではなく、回収漏れを知らせる安全装置です。
事故例12件と、止める証拠
ここでは、AI並列編集で起きやすい事故を、発生条件、見つけ方、予防策へ分けます。
事故1: 同じ作業ツリーで後勝ち上書き
AI-AとAI-Bが同じsrc/app.tsを読み、それぞれが全体を書き戻します。後から保存した側が先の変更を消しても、Gitは「二者の変更」として保持していないため、merge conflictになりません。
予防は一worktree一書き手です。見つける証拠は、作業開始前後のhash、editor履歴、最終diffです。
事故2: branch名だけ分けて同時作業したつもりになる
一つのfolderでAI-Aがbranchを切り替えた直後、AI-Bが古いbranch前提でコマンドを続けます。HEADとindexは作業ツリーで一つなので、AI-Bの前提が崩れます。
予防はlinked worktreeか別cloneです。git branch --show-currentとgit status --porcelain=v2 --branchを各工程の入口で記録します。
事故3: 同じbranchを複数worktreeへ無理に割り当てる
Gitは通常、別worktreeですでにcheckoutされているbranchを新たなworktreeへ割り当てることを拒否します。--forceで安全装置を越えると、同じbranchの先端を複数の場所から動かす競争になります。
予防は一branch一worktreeです。git worktree list --porcelainでbranchの重複を調べます。
事故4: 所有外ファイルを「ついでに」変更する
検索担当が認証moduleを整形し、テスト担当が共通設定を更新すると、各差分は小さくても採用範囲が膨らみます。テストが通っても指示違反は残ります。
予防は所有票と変更ファイルallowlistです。git diff --name-only相当の一覧をallowlistと比較し、範囲外が一件でもあれば未合格とします。
事故5: 生成物を全員が再生成する
二体が同じ目次、snapshot、bundle、schema生成物を更新します。生成器が同じでも、入力時点や環境の差で大きなdiffが発生します。
予防は生成物の所有者を統合担当一人にすることです。各workerはsourceだけを変更し、統合後に一回再生成します。
事故6: lockfileを別々に更新する
機能担当ごとに依存追加を許すと、同じlockfileへ別の解決結果が書かれます。text conflictがなくても、片方の依存が消える可能性があります。
予防は依存変更を一つの専用taskへ集約することです。manifestとlockfileの差分を対にしてレビューします。
事故7: untracked成果物を回収せずworktreeを消す
AIがレポートや画像を作ったものの、Gitに追跡されていません。通常removeが拒否したため、操作者がforceを付けて消し、成果物も失います。
予防はgit ls-files --others --exclude-standardの結果をゼロ件または承認済み一覧にすることです。削除前に絶対path、file size、必要ならhashを記録します。
事故8: main worktreeの.envがある前提でテストする
linked worktreeは別の作業directoryです。main側のuntrackedまたはignoredな.env、秘密、local database、依存folderは自動では現れません。テスト失敗をコード不具合と誤診することがあります。
予防は秘密を複製せず、必要な設定項目を安全なtemplateと環境注入で明示することです。Claude Code固有の.worktreeincludeは、Gitそのものの機能ではなく製品機能なので区別します。
事故9: folderだけ手動削除して管理情報を残す
Explorerやfilesystem操作でlinked worktreeのfolderを先に消すと、common Git directory内に管理情報が残ります。Git公式は通常git worktree removeを使い、手動削除後の古い管理情報にはpruneを案内しています。
予防は一覧、clean状態、回収証拠を確認した統合担当だけが正式手順で清掃することです。
事故10: Git worktree lockを編集排他と誤解する
lockしたので同じfileを複数AIが触っても安全だと思い込みます。しかし、worktree lockは主にprune、move、removeから管理情報を守るもので、file編集を止めません。
予防はlockに頼らず、別worktreeと所有票を使うことです。
事故11: submoduleの状態を親repositoryだけで判断する
親repositoryがcleanでも、submodule内が未初期化、別commit、変更あり、競合中という場合があります。Gitのsubmodule文書は、statusのprefixで未初期化、記録commitとの差、競合を示します。
予防はgit submodule status --recursiveと、必要な場合のsubmodule内statusを証拠へ加えることです。Git worktree文書ではsubmoduleを含むlinked worktreeのmoveに制限があるため、移動を通常操作と考えません。
事故12: Windows pathを文字列連結して誤操作する
C:\Users\山田 太郎\...のように日本語と空白を含むpathを引用符なしで組み立てると、shellが複数引数に分けます。文字化けを避けようとして別名へコピーすると、今度はどちらが正本か分からなくなります。
予防は絶対pathを記録し、PowerShellではsingle quoteと-LiteralPathを使い、Gitのpath表示には必要に応じてcore.quotepath=falseを一時指定します。自動処理は表示文字列を再解釈せず、機械向け形式をparserで扱います。
| 事故 | 最初に見る機械証拠 | 合格条件 |
|---|---|---|
| 1、2 | 現在branch、作業場所、diff | 各書き手の場所とbranchが一意 |
| 3 | worktree一覧 | 同じlocal branchの重複がない |
| 4 | 変更file一覧 | allowlist外がない |
| 5、6 | 生成物とlockfileの所有記録 | 統合担当以外が変更していない |
| 7、8 | untracked、ignored、環境要件 | 未回収成果物と秘密複製がない |
| 9、10 | worktree一覧のlock、prunable | lockの目的と清掃対象が一致 |
| 11 | submodule status | 記録commitと実状態を説明できる |
| 12 | 絶対pathとporcelain出力 | pathを欠損なく一意に特定できる |
統合担当は「merge係」ではなく採用責任者
並列作業の成否は、worker数より統合の質で決まります。統合担当は、単にbranchを結合するだけではありません。目的に照らして採用順を決め、競合時に両方の意図を読み、統合後の単一状態で検証し、未採用の成果を記録し、最後に清掃します。
| 段階 | 統合担当が確認すること | 証拠 | 停止条件 |
|---|---|---|---|
| 受付 | task、branch、worktree、所有範囲が一対一か | 割当表、worktree一覧 | 重複所有がある |
| 回収 | 成果が存在し、依頼外変更がないか | 絶対path、file一覧、diff | untracked成果が不明 |
| 個別検品 | 各branch単体で対象testが通るか | command、exit code、生出力 | test失敗または未実行 |
| 採用順決定 | schemaやinterfaceの依存順が正しいか | dependency表 | 前提branchが未合格 |
| 競合解消 | 両側の意図を保持した最終内容か | conflict file、設計、review | 正解を決める根拠がない |
| 統合後検証 | 結合した一つの状態でbuild、test、lintが通るか | command、exit code、生出力 | 個別合格でも統合後失敗 |
| 差分監査 | 最終diffが依頼範囲内か | changed files、diff summary | 勝手な変更がある |
| 清掃 | すべて回収済みで戻せるか | branch、commit、artifact記録 | 未commit、untracked、未採用 |
GitHubのpull request文書は、変更を提案し、議論し、レビューしてからmergeする協働の流れを説明しています。commit比較ではbaseとcompareを分けて確認できます。AI作業でも、この「提案と採用を分ける」考え方が使えます。
競合が出たときは、速く消すのではなく意味を選びます。GitHubのcommand lineでの競合解消は、同じ行の競合では最終的に取り込む変更を選び、新しいcommitとして解消すると説明しています。複雑な競合は、単純にoursまたはtheirsへ寄せず、共通ancestor、現在側、相手側を見比べます。
完了の証拠を四層で出す
AIの「完了しました」は採用証拠の一部にもなりません。最低でも、成果物、差分、実行、統合後状態の四層を分けます。AIが書く記事に機械の門番を付ける方法と同じく、主張と検査を対応させます。
| 証拠層 | 主張 | 必須項目 | 不合格例 |
|---|---|---|---|
| 成果物 | 指定場所にfileがある | 絶対path、size、必要ならhash | 「作成した」という文章だけ |
| 差分 | 指定範囲だけを変えた | changed files、diff、untracked一覧 | 一部fileだけ抜粋 |
| 個別実行 | task単体で検査に通る | command、exit code、生出力 | 「test済み」だけ |
| 統合実行 | 採用後の単一状態で動く | 統合後build、test、lint、代表操作 | workerごとの成功だけ |
| 要件対応 | 依頼条件を満たす | 要件と証拠の対応表 | 条件数と証拠数が合わない |
| 未確認 | 何を確かめていないか | 未実行理由、影響、次の検査 | 未確認を合格扱い |
報告の短い型は次の通りです。
状態: 個別合格、統合待ち
作業場所: D:\ai-lab\orion-search
branch: agent/search
変更file: 3件、所有範囲外0件
untracked: 0件
検査command: 架空の対象test command
exit code: 0
生出力: 保存先を明記
未確認: mainへ統合後の全体test
「全workerが終了した」と「productが完成した」を分けることが重要です。前者は並列処理の終了、後者は統合後の合格です。AIエージェントとチャットAIの違いで説明したように、道具を使えるAIほど、発言ではなく外部状態を読み直します。
Windowsと日本語ユーザー名の注意
Windowsでworktreeを使うときは、Gitの仕組みに加えてpath、shell、長いdirectory名、権限、実行中processを考えます。
C:\Users\山田 太郎\開発\...のようなpathは常に引用します。- PowerShellのfilesystem操作では、文字列をwildcardとして解釈させたくない場合に
-LiteralPathを使います。 - AIへ渡す作業場所は相対pathだけでなく絶対pathも記録します。
- 同じrepositoryの似た名前のworktreeを大量に並べず、task IDを入れます。
- 開発server、test runner、editorがfileを開いていると、folderの移動や削除がOS側で失敗することがあります。processを確認してから清掃します。
- path表示が引用またはescapeされていても、元fileが壊れたとは限りません。表示設定と実体を分けます。
- user profile内の秘密や認証情報をworktreeへcopyする自動化を既定にしません。
- path長やtool固有の制約はGit以外にもあるため、使用するcompiler、package manager、test runnerでも確認します。
日本語pathを避けるためだけに別の英字folderへ手動copyすると、Gitのlinked metadataとの接続を壊す可能性があります。Git公式は移動にgit worktree move、接続が古くなった場合にgit worktree repairを用意していますが、submoduleを含むlinked worktreeのmoveには制限があります。場当たり的なExplorer移動ではなく、まず一覧と公式制約を確認します。
untracked fileとignored fileは「見えない成果」
Gitはtracked fileの差分管理に強い一方、untracked fileはcommit履歴に入りません。ignored fileは通常のstatusにも出にくいため、AIがそこへ重要成果を出すと回収漏れが起きます。
| file種別 | 通常のdiff | worktree間の共有 | 主な危険 | 運用 |
|---|---|---|---|---|
| tracked | 表示される | checkoutしたcommitに応じて各worktreeへ展開 | merge conflict | 所有者とdiffを検査 |
| untracked | 通常diffには出ない | 共有されない | remove時の消失、回収漏れ | 専用一覧で確認 |
| ignored | 通常statusで目立たない | 共有されない | 秘密、cache、生成物の見落とし | 役割を分類し重要成果を置かない |
| Git外artifact | Gitは管理しない | 保管方法次第 | 出所とversionが不明 | task ID、hash、生成元を記録 |
Gitのstatus文書、diff文書、gitignore文書を分けて参照してください。git cleanはuntracked fileを削除するcommandであり、git-clean文書にもforce要件がありますが、自動清掃へ安易に組み込みません。まずdry run相当の確認と回収が必要です。
秘密fileは「worktreeへないからcopyする」と短絡しません。必要な秘密を安全に注入できないなら、秘密なしで可能なtestを先に行い、認証を要する検査は未確認として残します。サンドボックスと権限の設計はAIコーディングエージェントのサンドボックス入門を参照してください。
submoduleがあるrepositoryは別のGitとして扱う
submoduleは親repositoryの普通のdirectoryではなく、別repositoryの特定commitを参照する仕組みです。親側のindexにはsubmoduleのcommitが記録されますが、submodule内部には独自のHEAD、index、作業ファイルがあります。
そのため、次を別々に確認します。
| 確認対象 | 親repository | submodule |
|---|---|---|
| 現在branch | 親のbranch | submodule側はdetached HEADの場合もある |
| status | 親fileとgitlink | submodule内部のtracked、untracked |
| diff | 記録commitの変化 | 内部fileの実差分 |
| remote | 親のremote | submodule独自のremote |
| merge conflict | 親fileとgitlink | submodule内部の競合 |
| worktree清掃 | linked worktree全体 | submoduleの初期化と変更も確認 |
親がcleanという一行だけで清掃しません。git submodule status --recursiveの結果と、変更が疑われるsubmodule内のstatusを保存します。複数エージェントへsubmoduleを含む作業を割り当てる場合は、親側gitlinkの更新担当も一人に固定します。
清掃は最後の独立工程にする
清掃は便利な後片付けではなく、成果を消せる変更操作です。統合担当が次の順番を守ります。
- workerの終了通知を受ける。
- worktree一覧を読み、対象path、branch、HEADを照合する。
- tracked変更、stage済み変更、untracked file、submodule状態を確認する。
- 必要成果の絶対path、size、hashまたはcommitを記録する。
- 採用branchへ成果が回収されたことを確認する。
- 統合後検査を実行し、生出力を保存する。
- worktree lockの理由が残っていないか確認する。
- 通常のremoveが可能なclean状態にする。
- 正式なworktree管理commandで外す。
- 一覧を再読し、古い管理情報や取り違えがないことを確かめる。
本稿ではこれらの削除操作を実行していません。実運用でも、forceは「通常操作が失敗したから付ける追加option」ではありません。失敗理由を読み、成果回収済みという独立証拠がある場合だけ、人が影響を判断します。復旧設計は家庭で始める3-2-1バックアップの考え方と同じく、消す前に戻り先を用意します。
最小運用テンプレート
初めてAIを並列化するなら、最初から多数を投入せず、二つの独立taskと一人の統合担当で仕組みを検証します。性能比較ではなく、運用の欠陥を先に見つけるためです。Claude CodeとCodexの役割比較はClaude CodeとCodexの使い分けも参考になりますが、どの製品でも所有と証拠は必要です。
| 時点 | worker A | worker B | 統合担当 |
|---|---|---|---|
| 開始前 | task Aの所有票を確認 | task Bの所有票を確認 | 重複fileと依存を確認 |
| 作業中 | 専用worktreeだけ編集 | 専用worktreeだけ編集 | 共通fileを予約 |
| 個別終了 | diffとtest証拠を提出 | diffとtest証拠を提出 | 範囲外変更を拒否 |
| 統合 | 待機 | 待機 | 一件ずつ採用 |
| 統合後 | 必要なら説明 | 必要なら説明 | 全体検査と代表操作 |
| 清掃 | 勝手に消さない | 勝手に消さない | 回収済みを確認して実施 |
AIへ渡す短い禁止事項は次のように書けます。
同じ作業ツリーを他担当と共有しない。
割当外のfile、branch、Git設定を変更しない。
共通生成物とlockfileを再生成しない。
commit、merge、push、worktree清掃は統合担当だけが行う。
完了報告には絶対path、変更file、command、exit code、生出力を含める。
未実行の検査を成功と書かない。
FAQ
1. branchを分けるだけでは駄目ですか
一人が一つのfolderで交互に作業するなら使えます。複数の書き手が同時に動く場合、一つの作業ツリーのHEAD、index、実fileは同時利用に向かないため、linked worktreeまたは別cloneで作業場所も分けます。
2. worktreeを使えばmerge conflictはなくなりますか
なくなりません。作業中の直接上書きは避けられますが、別branchが同じ行や矛盾する仕様を変更すれば統合時に競合します。
3. 同じfileを別worktreeで編集してもよいですか
技術的には可能ですが、原則として避けます。どうしても必要なら変更する関数や行の境界、採用順、統合担当を先に決めます。
4. 一つのlocal branchを複数worktreeで使えますか
Gitは通常、すでに別worktreeでcheckout中のbranchを割り当てる操作を拒否します。forceで回避せず、taskごとにbranchを分けます。
5. linked worktreeとcloneはどちらが安全ですか
目的によります。同じrepositoryの履歴とobjectを共有しつつ作業fileを分けたいならworktreeが効率的です。repository設定やrefsも強く分離したい、別端末や別資格情報境界で動かしたいなら別cloneを検討します。別cloneは同期とディスクの負担が増えます。
6. git worktree lockで他のAIの編集を止められますか
止められません。worktree lockは主に管理情報をprune、move、removeから守る機能です。fileの同時編集防止には、別worktreeと所有票を使います。
7. main worktreeの.envはlinked worktreeから見えますか
通常、main側だけにあるuntrackedまたはignored fileは別worktreeへ自動展開されません。秘密をcopyする前に、安全な環境注入と必要性を確認します。
8. node_modulesやbuild cacheは共有されますか
作業directory内にあるものはworktreeごとに別です。repository外の共通cacheをtoolが使う場合は共有される可能性があるため、そのtoolの公式仕様と設定を確認します。
9. 生成物は各AIに作らせるべきですか
共通生成物は統合担当だけが最後に作る方が安定します。worker固有の中間成果はtask IDごとの別directoryへ出し、正本と混ぜません。
10. untracked fileが一件でもあれば失敗ですか
必ずしも失敗ではありません。ただし、何のfileか、必要な成果か、秘密か、消してよいcacheかを分類できるまで清掃は止めます。
11. submoduleがあるとworktreeは使えませんか
一律に使えないわけではありません。ただし、submoduleには独自のGit状態があり、linked worktreeのmoveなどに公式上の制限があります。親とsubmoduleを別々に検査します。
12. Windowsの日本語pathは使えますか
使えますが、shellや周辺toolが正しく引用し処理できることを確認します。絶対pathを引用し、PowerShellのfilesystem操作では必要に応じて-LiteralPathを使います。
13. 完了報告で最低限必要なものは何ですか
成果物の絶対path、変更file一覧、untracked一覧、実行command、exit code、生出力、未確認事項です。統合後には同じ検査を単一の採用状態でも行います。
14. worker全員のtestが通ればmainへ入れてよいですか
まだ足りません。個別に通った変更同士を合わせると、interface、schema、依存、生成物が衝突することがあります。統合後testが必要です。
15. merge conflictはAIへ自動解消させてよいですか
候補作成や差分説明は任せられますが、正解は両branchの目的と要件で決まります。統合担当が最終内容とtest結果を確認します。
16. worktreeのfolderをExplorerで消してよいですか
避けます。Gitの管理情報が残るため、回収とclean状態を確認し、正式なworktree管理手順を使います。すでに手動移動や削除が起きた場合は、Git公式のrepairやpruneの説明を読んで対象を確認します。
17. agent teamのtask lockがあれば所有票は不要ですか
不要にはなりません。task取得の重複を防いでも、別taskが同じfileや生成物を触る可能性があります。taskとfileの対応表を残します。
18. 何体まで並列にすべきですか
固定の正解はありません。独立taskの数、統合担当が検品できる量、共通fileの少なさ、実行環境の資源で決めます。workerを増やして統合待ちと競合が増えるなら、並列数を下げます。
採用前チェックリスト
- 一task、一branch、一worktree、一編集責任者になっている
- 同一fileの所有重複がない
- schema、lockfile、生成物の担当が統合担当へ集約されている
- 各worktreeの絶対path、branch、HEADを記録した
- 変更file一覧をallowlistと照合した
- untracked fileとignored成果の扱いを確認した
- submoduleの有無と状態を確認した
- 個別testのcommand、exit code、生出力がある
- 競合解消の判断者が一人に決まっている
- 統合後のbuild、test、lint、代表操作を実行した
- 未確認事項を合格へ丸めていない
- 清掃前に成果回収と戻り先を確認した
まとめ
AIエージェントの並列化で最も危険なのは、AIの能力不足より、同じ場所、同じfile、同じbranch、同じ生成物を誰が所有するか決めないまま人数だけ増やすことです。
同じ作業ツリーは一人の書き手に限定します。branchを分けるだけでなく作業directoryもlinked worktreeで分けます。worktreeはHEADとindexと実fileを分離しますが、Git object、通常のrefs、標準のrepository設定は共有すると理解します。別cloneはさらに強く分離できますが、同期と環境構築の負担が増えます。
最後に、統合担当を一人へ固定します。変更file、untracked file、個別test、競合解消、統合後test、清掃証拠を一つの採用判断へ集めます。workerの終了は作業の完了ではなく、統合後の単一状態が検査に通った時が完了です。
Sources
以下は2026年7月24日に確認した公式資料です。製品機能とGitの仕様は更新されるため、実運用前にリンク先の最新版を再確認してください。
需要とAIエージェント運用
- OpenAI, Introducing Codex
https://openai.com/index/introducing-codex/ - OpenAI, Introducing the Codex app
https://openai.com/index/introducing-the-codex-app/ - OpenAI, Codex
https://openai.com/codex/ - Anthropic, Run agents in parallel
https://code.claude.com/docs/en/agents - Anthropic, Run parallel sessions with worktrees
https://code.claude.com/docs/en/worktrees - Anthropic, Orchestrate teams of Claude Code sessions
https://code.claude.com/docs/en/agent-teams - Anthropic, Create custom subagents
https://code.claude.com/docs/en/sub-agents - Anthropic, Common workflows
https://code.claude.com/docs/en/common-workflows
Gitの構造と操作
- Git, git-worktree Documentation
https://git-scm.com/docs/git-worktree - Git, User Manual
https://git-scm.com/docs/user-manual - Git, gitrepository-layout Documentation
https://git-scm.com/docs/gitrepository-layout - Git, git-branch Documentation
https://git-scm.com/docs/git-branch - Git, git-checkout Documentation
https://git-scm.com/docs/git-checkout - Git, git-merge Documentation
https://git-scm.com/docs/git-merge - Git, git-status Documentation
https://git-scm.com/docs/git-status - Git, git-diff Documentation
https://git-scm.com/docs/git-diff - Git, git-clone Documentation
https://git-scm.com/docs/git-clone - Git, git-submodule Documentation
https://git-scm.com/docs/git-submodule - Git, gitignore Documentation
https://git-scm.com/docs/gitignore - Git, git-clean Documentation
https://git-scm.com/docs/git-clean
GitHubでの比較、review、競合解消
- GitHub Docs, Pull requests
https://docs.github.com/en/pull-requests/reference/pull-requests - GitHub Docs, Comparing commits
https://docs.github.com/en/pull-requests/how-tos/commit-changes/comparing-commits - GitHub Docs, Merge conflicts
https://docs.github.com/en/pull-requests/reference/merge-conflicts - GitHub Docs, Resolving a merge conflict using the command line
https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-using-the-command-line - GitHub Docs, Resolving a merge conflict on GitHub
https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-on-github - GitHub Docs, Cloning a repository
https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository