本文へスキップ
Gitワークツリー

GitワークツリーでAIコーディングエージェントを並列実行する方法

エージェントごとに専用のGitワークツリーを用意します。リポジトリの履歴を共有しつつ、自分のブランチを持つ別の作業ディレクトリです。git worktree addで作成し、その中でエージェントを起動し、作業が終わったらブランチをマージしてワークツリーを削除します。MAOのレイヤーは同じことをキャンバス上で行い、マージの前にチェックします。

  • ワークツリーは、1つのリポジトリを共有しながら自分のブランチを持つ2つ目のチェックアウトです
  • Gitは同じブランチを2つのワークツリーでチェックアウトすることを拒否します
  • .envやnode_modulesなどの無視されたファイルは、新しいワークツリーにはありません
著者:更新日:約14分で読めます

AIコーディングエージェントを互いの作業を上書きさせずに並列で動かすには、エージェントごとに専用のGitワークツリーを用意します。1つのリポジトリを共有しながら、自分のブランチを持つ別の作業ディレクトリです。git worktree add -b で作成し、その中でエージェント(Claude Code、Codex、Gemini CLIなど)を起動し、作業が終わったらブランチをマージしてワークツリーを削除します。MAOでは、レイヤーがこのワークツリーです。ナビゲーターから作成し、取り込む前にチェックが入ります。

Gitワークツリーとは?

ワークツリーは、同じリポジトリにつながった追加の作業ディレクトリで、それぞれが自分のブランチをチェックアウトしています。

Git自身のドキュメントによると、1つのリポジトリは複数の作業ツリーを持てるので、複数のブランチを同時にチェックアウトできます。git clone や git init が作ったチェックアウトがメインワークツリーで、追加したものはそれぞれリンクされたワークツリーです。リンクされたワークツリーは、HEAD やインデックスのようなワークツリーごとのファイルを除いて、すべてをリポジトリと共有します。

実際には、各ワークツリーが自分のファイル、自分のブランチ、自分のステージ済みの変更を持ち、コミット、ブランチ、オブジェクトストアは共有されます。あるワークツリーで作ったコミットは、pushやfetchなしで、ほかのすべてのワークツリーからすぐに見えます。

並列のコーディングエージェントに別々のワークツリーが必要なのはなぜ?

1つのチェックアウトにいるエージェントは、同じファイルを編集し、1つのブランチを共有するからです。

2つのエージェントが同じディレクトリで作業すると、一方の書きかけの変更がもう一方の出発点になり、テストの実行にはどちらも組み合わせるつもりのなかった編集が混ざり、1つのターミナルでの git switch がすべてのエージェントの足元のファイルを変えてしまいます。エージェントごとに1つのワークツリーを使えば、各エージェントは自分のブランチ上で自分のファイルを編集し、何を組み合わせるかはブランチのマージであなたが決めます。

エージェントごとにワークツリーを用意するには?

メインのチェックアウトから、エージェントごとに1つのワークツリーと新しいブランチを追加し、それぞれのフォルダでエージェントを起動します。

  1. メインのチェックアウトで、エージェントごとにワークツリーと新しいブランチを作成します。パスはフォルダの置き場所です。リポジトリと同じ階層に置くと、プロジェクトのファイルに混ざりません。
  2. プロジェクトの実行に必要な無視されたファイル(.env など)をコピーし、各ワークツリーで依存関係をインストールします。
  3. 各ワークツリーで、それぞれ専用のターミナルからエージェントを1つずつ起動します。
  4. 今あるワークツリーは、いつでも git worktree list で確認できます。
git worktree add ../myapp-api -b agent/api
git worktree add ../myapp-tests -b agent/tests

cp .env ../myapp-api/
cp .env ../myapp-tests/

cd ../myapp-api && claude      # agent 1
cd ../myapp-tests && claude    # agent 2

git worktree list

git worktree list は、まずメインワークツリーを、続いてリンクされた各ワークツリーを、チェックアウト中のコミットとブランチとともに表示します。

/home/me/myapp        d3d2dd1 [main]
/home/me/myapp-api    d3d2dd1 [agent/api]
/home/me/myapp-tests  d3d2dd1 [agent/tests]

スクリプトでは、git worktree list --porcelain を使うと、Gitのバージョンが変わっても安定した形式で出力されます。すでにあるブランチをエージェントに渡すときは、-b を省きます(git worktree add ../myapp-fix fix/login)。

エージェントの作業をマージして片付けるには?

メインのチェックアウトでエージェントのブランチをマージし、ワークツリーを削除してからブランチを削除します。

  1. エージェントに、自分のブランチへ作業をコミットさせます。
  2. メインのチェックアウトで、ほかのブランチと同じようにマージします。
  3. ワークツリーを削除します。Gitが削除するのはクリーンなワークツリー、つまり追跡されていないファイルがなく、追跡中のファイルにも変更がないものだけです。
  4. マージ済みのブランチを削除します。ワークツリーがそのブランチをチェックアウトしている間、Gitはブランチの削除を拒否するので、先にワークツリーを削除します。
cd ../myapp
git merge agent/api
git merge agent/tests

git worktree remove ../myapp-api
git worktree remove ../myapp-tests
git branch -d agent/api agent/tests

ワークツリーに変更や追跡されていないファイルがあって git worktree remove が拒否した場合は、残したいものをコミットするか移動するか、--force を付けて破棄します。ワークツリーのフォルダを手で削除してしまった場合は、git worktree list がそれを prunable と表示し、git worktree prune が残った記録を削除します(git worktree prune -n は削除対象を表示するだけです)。

ワークツリーでよくある問題は?

問題のほとんどは、すでにチェックアウトされているブランチ、Gitが追跡しないファイル、そしてワークツリー同士がまだ共有しているものから生じます。

  • 同じブランチを2回チェックアウトすることはできません。 git worktree add は、ほかのワークツリーがチェックアウト中のブランチを拒否し、ワークツリー内での git switch も同様です。メインのチェックアウトが使っている main も対象になるので、ワークツリーを main に切り替えるのではなく、メインのチェックアウトでマージします。エージェントごとに -b で新しいブランチを作ります。
  • 無視されたファイルや追跡されていないファイルはコピーされません。 新しいワークツリーには、Gitが追跡しているファイルしかありません。.env、node_modules、ビルド成果物、ローカル設定は、作られたチェックアウトに残るので、各ワークツリーでコピーするか再インストールします。
  • 無視されたファイルは確認なしに削除されます。 git worktree remove を止めるのは、変更されたファイルか追跡されていないファイルだけです。コピーした無視対象の .env しかないワークツリーは、それごと削除されます(Git 2.56.0で確認)。
  • ポートが衝突します。 各ワークツリーはプロジェクトの完全なコピーなので、2つのワークツリーで開発サーバーを起動すると、サーバーが2つ立ち上がります。両方が同じ固定ポートで待ち受けると、2つ目は起動に失敗します。ワークツリーごとに別のポートを設定します(たとえばそれぞれの .env で)。
  • フォルダを削除すると記録が残ります。 rm でワークツリーのディレクトリを消すと、git worktree prune を実行するかGitが期限切れで消すまで、その記録がリポジトリに残ります。代わりに git worktree remove を使います。
  • サブモジュールのサポートは完全ではありません。 Gitのドキュメントは、複数のチェックアウトをまだ実験的な機能とし、サブモジュールのサポートは不完全で、スーパープロジェクトを複数チェックアウトすることは推奨しないとしています。サブモジュールを含むワークツリーの削除には --force が必要です。

Claude Codeは自分でワークツリーを作成できる?

できます。ワークツリー用のフラグで、ワークツリーとブランチを作成し、その中でセッションを開始します。

Claude Codeのドキュメントによると、claude --worktree feature-auth(または -w)は、リポジトリのルートにある .claude/worktrees/feature-auth/ にワークツリーを作り、worktree-feature-auth という新しいブランチに置きます。2つ目のターミナルで別の名前を付けてもう一度実行すると、2つ目の独立したセッションになります。同じページにある詳細は次のとおりです。

  • 新しいワークツリーは、worktree.baseRef の設定が "head" でない限り、リポジトリのデフォルトブランチから分岐します。
  • プロジェクトのルートに置いた .worktreeinclude ファイル(.gitignore と同じ書式)は、一致するGitの無視対象ファイル(.env など)を新しいワークツリーごとにコピーします。
  • 終了時、名前のないセッションのクリーンなワークツリーはブランチごと削除されます。変更やコミットがあるワークツリーでは、残すか削除するかを尋ねられます。
  • フロントマターに isolation: worktree を持つカスタムサブエージェントは、常に専用の一時的なワークツリーで動きます。

ドキュメントでは、.claude/worktrees/ を .gitignore に加えて、これらのワークツリーがメインのチェックアウトで追跡されていないファイルとして表示されないようにすることも勧めています。

1つのチェックアウト、ワークツリー、クローン、MAOのレイヤーのどれがよい?

ワークツリーとレイヤーは、1つのリポジトリを共有しながら各エージェントに専用のファイルを与えます。クローンはより強く分離しますが、作業を共有するにはpushとfetchが必要です。

方法エージェントごとの専用ファイルfetchなしでのコミット共有作業の戻し方片付けエージェントごとの準備
1つのチェックアウトいいえ、全エージェントが同じファイルを編集はい、1つしかないため最初から混ざっている片付け不要不要
Gitワークツリーはい、それぞれにフォルダとブランチはい、ワークツリーは1つのリポジトリを共有ブランチを git mergegit worktree remove の後に git branch -dgit worktree add -b を1回
別々のクローンはい、それぞれに完全なリポジトリいいえ、各クローンが独自のリポジトリとリモート追跡ブランチを持つブランチをpushまたはfetchしてからマージクローンのフォルダを削除git clone を1回
MAOのレイヤーはい、各レイヤーが自分のブランチ上のGitワークツリーはい、レイヤーは1つのリポジトリのワークツリーLand… がチェックしてからGroundへマージまたはfast-forward取り込み後はデフォルトでアーカイブ、復元可能New layer でレイヤー名とブランチ名を入力

MAOのレイヤーはワークツリーをどう使う?

MAOのレイヤーは、自分のブランチと自分のキャンバスを持つGitワークツリーで、ナビゲーターから作成、切り替え、取り込みを行います。

  1. 作成。 ナビゲーターのレイヤーレールで New layer を選び、レイヤー名とブランチ名を入力します。Groundの配置を出発点としてコピーすることもできます。コピーされたノードは下書きとして始まり、権限をバイパスする起動オプションはコピーされません。
  2. 作業。 レールでレイヤーに切り替え、そこにエージェントを置きます。切り替えるとアクティブなキャンバスとワークツリーが変わりますが、何もマージされません。レイヤーのキャンバスはワークツリー内のファイルではなくMAO自身の状態に保存されるので、git status には表示されません。
  3. 報告。 レイヤー上のエージェントは、mao layer status で作業の進み具合を投稿できます。blocked または review にしたレイヤーは、要対応として示されます。
  4. 取り込み。 Groundに切り替え、レイヤーのメニューで Land… を選びます。MAOは衝突とコミットされていない変更をチェックし、マージまたはfast-forwardの前に取り込み先のブランチを表示します。ブランチのリセット、強制的な変更、作業のstashは一切行わず、チェック後にブランチが動いていれば取り込みを拒否します。
  5. アーカイブ。 取り込んだレイヤーは、Keep the layer をオンにしない限りアーカイブされます。アーカイブは元に戻せます。レイヤーを削除するコマンドはありません。

エージェントは自分のターミナルから、自分のレイヤーの状態を投稿します。オーケストレーターに指定されたエージェントは、さらにレイヤーの作成、取り込み、アーカイブ、復元を行い、新しいエージェントをレイヤーに置くこともできます。

mao layer status --state review --progress 3/5
mao layer land "api"
mao layer archive "api"
mao layer restore "api"

よくある質問

使えません。git worktree add はほかのワークツリーがチェックアウト中のブランチを拒否し、ワークツリー内での git switch も拒否します。ワークツリーごとに -b で新しいブランチを作ります。

しません。新しいワークツリーにはGitが追跡しているファイルしかないので、.env や node_modules などの無視されたファイルは、ワークツリーごとにコピーするか再インストールする必要があります。Claude Codeの .worktreeinclude ファイルを使うと、Claude Codeが作るワークツリーにGitの無視対象ファイルをコピーできます。

違います。クローンは独自のブランチとオブジェクトを持つ別のリポジトリで、クローン同士はpushとfetchで作業をやり取りします。ワークツリーは1つのリポジトリを共有するので、あるワークツリーでのコミットはすぐにすべてのワークツリーから見えます。

Gitはそのワークツリーの記録を残し、git worktree list はそれをprunableと表示します。git worktree prune で記録を片付け、次からは git worktree remove を使います。

はい。MAOの各レイヤーは自分のブランチ上のGitワークツリーで、New layer を選んでブランチ名を入力すると作成されます。MAOが衝突とコミットされていない変更をチェックした後、キャンバスからGroundに取り込みます。

出典

2026-10-28に確認。

ご質問は?Discordで質問するか、hello@miguer.comまでメールでお知らせください。

自分のリポジトリで試す

エージェントをひとつのキャンバスに。

キャンバスの全機能を使える7日間のトライアル。カードは不要です。