はじめに
「PRのレビュー待ち、何もすることがない」──この空白時間に悩んだ経験は、多くの開発者にあるのではないでしょうか。
僕もかつてはそうでした。PRを出したら、レビューが返ってくるまでの間、別のブランチに切り替えて作業しようとしてgit stashの山を築き、環境構築のやり直しに時間を奪われ、結局「レビュー待ち」を理由にSlackを眺めてしまう。そんな日々を送っていました。
それが、Claude Code × Git Worktree の組み合わせを導入してから、世界が変わりました。PRを出した30秒後には、もう次の機能の実装に取りかかっている。レビューコメントが来たら、ディレクトリを移動するだけで元の作業に戻れる。「待ち時間」という概念が、開発フローから消えたのです。
この記事では、僕が個人プロジェクトで実践してきた並列開発ワークフローを、具体的なコードとともに紹介します。
この記事で学べること
- git worktreeの基本と並列開発への応用
- Claude Code Skillによるworktree自動化の実装
- 実運用で得たTipsとトラブルシューティング
なぜ並列開発が必要になったのか
僕が並列開発の必要性を痛感したのは、個人で開発しているレシピクリップというiOSアプリのプロジェクトでした。
Claude Codeを活用してフロントエンド・バックエンド・AIエージェントを並行して開発していると、ある壁にぶつかります。ブランチを切り替えるたびに発生する、あの面倒な儀式です。
-
node_modulesの再インストール(フロントエンドとバックエンドで異なるため、切り替えのたびにnpm installが走る) -
.envファイルの環境変数の再設定(ポート番号やAPI keyの切り替え) - Claude Codeのコンテキストリセット(これが一番痛い)
特に3つ目が深刻でした。Claude Codeはセッション内で蓄積した文脈──ファイル構成の理解、設計方針の把握、直前の変更履歴──これらがブランチ切り替えで全てリセットされます。せっかく「このプロジェクトの構造を理解してもらった」状態が、git checkout一発で白紙に戻るのです。
つまり、Claude Codeセッションとブランチが1:1で対応する環境が必要でした。
逐次開発と並列開発の体感差を、表にまとめてみます。
| 逐次開発 | 並列開発(worktree) | |
|---|---|---|
| ブランチ切替 | stash→checkout→pop | cd で移動するだけ |
| 環境構築 | 毎回再構築 | 初回のみ |
| Claude Codeセッション | 切替のたびにコンテキスト喪失 | 各worktreeで独立維持 |
| PRレビュー待ち | 作業停止 or stash地獄 | 別worktreeで継続 |
この表を見れば一目瞭然ですが、実際に体験するとその差はさらに大きく感じます。「ブランチを切り替える」という行為そのものが、思考の切り替えコストを伴うからです。一方、cdでディレクトリを移動するだけなら、物理的にデスクの上で書類を入れ替える感覚に近い。思考のコンテキストも自然に切り替わります。
開発元Anthropicと先進企業の実践
僕がworktreeベースの並列開発を実践し始めてしばらく経った頃、興味深い記事を見つけました。Claude Codeの開発に携わるBoris Cherny氏の開発手法を紹介した記事と、incident.ioのエンジニアリングブログです。
Anthropicチームの標準化
Boris Cherny氏本人はgit checkoutを使うそうですが、Anthropicのチーム全体ではgit worktreeが標準化されているとのこと。特に印象的だったのは、Adam Morris氏がClaude Desktopにworktreeのネイティブサポートを実装したというエピソードです。チーム内ではza、zb、zcといったシェルエイリアスでworktree間を瞬時に移動し、専用の「分析worktree」でログ閲覧やBigQueryクエリを実行するという運用まで確立されていました。
Boris氏はローカルで5セッション、claude.ai/codeで5〜10セッションを並列で走らせているそうです。この規模になると、もはやworktreeなしでは成り立ちません。
incident.ioの成果
もう一つ、incident.ioのチームの事例も共感するポイントが多いものでした。彼らは自作のbash関数wでworktree操作を簡略化し、Plan Modeを活用してClaude Codeに作業を任せている間に別のworktreeで作業する、という運用を確立しています。「ジュニア開発者のチームを並列管理する感覚」という表現が、まさに僕の体感と一致しました。
incident.ioの成果も具体的です。30秒のプロンプト入力と10分の処理で機能実装が完了し、API最適化ではわずか$8のコストで18%の高速化を達成したと報告しています。
Anthropic公式ドキュメントでも、git worktreeによる並列セッション運用は「the single biggest productivity unlock(単一最大の生産性向上)」と位置づけられています。大げさではないと、僕の実体験からも断言できます。自分が試行錯誤しながら辿り着いたワークフローが、公式にも推奨されるベストプラクティスだった──これは素直に嬉しい発見でした。
git worktree 超入門
ここで、git worktreeをまだ使ったことがない方のために、基本を整理しておきます。
git worktreeとは
git worktreeは、1つのGitリポジトリから複数の作業ディレクトリを作成するGitの標準機能です。通常、Gitリポジトリには1つの作業ディレクトリしかありませんが、worktreeを使うと、同じリポジトリの異なるブランチを、それぞれ独立したディレクトリとして同時に展開できます。
重要なのは、.gitの実体(コミット履歴やオブジェクトデータベース)は元のリポジトリと共有されるという点です。つまり、あるworktreeでコミットした変更は、他のworktreeからも参照できます。git cloneで複数コピーを作るのとは根本的に異なります。
基本コマンド
覚えるべきコマンドは4つだけです。
# 新規ブランチで作成(mainから分岐)
git worktree add .worktrees/feature-a -b feature/feature-a main
# 既存ブランチで作成
git worktree add .worktrees/bugfix bugfix/issue-123
# 一覧表示
git worktree list
# 削除
git worktree remove .worktrees/feature-a
git checkout との違い
| git checkout | git worktree | |
|---|---|---|
| 作業ディレクトリ | 1つを共有 | ブランチごとに独立 |
| 未コミットの変更 | stashが必要 | そのまま残る |
| 同時並行作業 | 不可 | 可能 |
| ディスク使用量 | 最小 | ブランチ分増加 |
| Claude Codeセッション | 1つだけ | 複数同時起動可 |
ディスク使用量が増加する点はデメリットですが、.gitのオブジェクトデータベースは共有されるため、git cloneを複数作るよりは遥かに軽量です。
worktree配置の設計判断
僕は.worktrees/というディレクトリにworktreeを集約するパターンを採用しています。リポジトリのルートにfeature-a/、bugfix-123/と散らばるよりも、.worktrees/配下にまとめたほうが見通しが良く、.gitignoreへの追加も1行で済みます。
# .gitignore
.worktrees/
ドットプレフィックスにしているのは、通常のディレクトリ一覧で表示されないようにするためです。worktreeは開発の「裏方」なので、目立たない場所にあるほうが自然です。
なお、git worktreeの詳細な仕様はGit公式ドキュメントで確認できます。本記事では実用上必要な範囲に絞って紹介しましたが、git worktree lockやgit worktree moveなど、より高度な操作も用意されています。
自動化スキルの実装:create-worktree
なぜスキル化したか
基本コマンドだけでworktreeを作成することは簡単ですが、実際の開発では追加の作業が必要になります。
-
.envファイルのコピーと、ポート番号の書き換え -
node_modulesのインストール - 各種設定ファイルのコピー
特にポート競合は頻発する問題でした。複数のworktreeで同時にdev serverを起動すると、全てがポート3000を使おうとして衝突します。毎回手動でポート番号を変えるのは、まさに「トイル(繰り返しの手作業)」です。
そこで、これらの手順をClaude Code Skillとして自動化しました。
Agent Skillsの仕組み
Agent Skillsとは、SKILL.mdというマークダウンファイルに手順を記述し、Claude Codeが/<skill name>コマンドや必要に応じでAIが判断して呼び出せるようにする仕組みです。シェルスクリプトのラッパーとして機能し、Claude Codeが状況に応じて適切にパラメータを判断して実行してくれます。
ブランチ自動作成
create-worktreeスキルの中核は、ブランチの存在確認と自動作成です。
FEATURE_NAME="$1"
BRANCH_NAME="feature/${FEATURE_NAME}"
WORKTREE_DIR=".worktrees/${FEATURE_NAME}"
if git show-ref --verify --quiet "refs/heads/${BRANCH_NAME}"; then
# 既存ブランチからworktree作成
git worktree add "${WORKTREE_DIR}" "${BRANCH_NAME}"
else
# 新規ブランチ作成
git worktree add -b "${BRANCH_NAME}" "${WORKTREE_DIR}" main
fi
git show-ref --verifyで既存ブランチの有無を確認し、あればそのブランチでworktreeを作成、なければmainから新規ブランチを切ります。「feature-Aを途中まで進めてworktreeを削除した後、もう一度作り直す」というケースにも対応できます。
ポート番号ランダム化(独自の工夫)
並列開発で最も厄介なのが、ポート競合の問題です。Claude Codeに聞いて自動ポートランダム化機能を実装してもらいました。
generate_random_port() {
echo $((RANDOM % 50000 + 10000))
}
RANDOM_FRONTEND_PORT=$(generate_random_port)
RANDOM_BACKEND_PORT=$(generate_random_port)
RANDOM_AGENT_PORT=$(generate_random_port)
sed -e "s/^FRONTEND_PORT=.*/FRONTEND_PORT=${RANDOM_FRONTEND_PORT}/" \
-e "s/^BACKEND_PORT=.*/BACKEND_PORT=${RANDOM_BACKEND_PORT}/" \
-e "s/^AGENT_PORT=.*/AGENT_PORT=${RANDOM_AGENT_PORT}/" \
".env" > "${WORKTREE_DIR}/.env"
10000〜59999の範囲でランダムにポートを割り当てることで、複数worktreeで同時にdev serverを起動しても競合しません。sedでメインリポジトリの.envをテンプレートとして読み取り、ポート番号だけを書き換えた新しい.envをworktreeに配置します。
ちなみに、先ほど紹介したincident.ioのチームも、DB接続やポート衝突の課題に言及していました。並列開発を実践する上で、誰もがぶつかる壁のようです。
.worktree.confによるカスタマイズ
プロジェクトによっては、コピーすべきファイルや実行すべきセットアップコマンドが異なります。create-worktreeでは.worktree.confという設定ファイルを用意し、プロジェクト固有のカスタマイズを記述できるようにしています。これにより、異なるプロジェクトでも同じスキルを再利用できます。
完全なソースコードはGitHub: create-worktreeで公開しています。
自動化スキルの実装:worktree-cleanup
worktreeの作成と同じくらい重要なのが、適切なクリーンアップです。ここでの「適切」とは、安全にという意味です。
cleanup時の落とし穴
git worktree removeは、未コミットの変更を含むworktreeでも(--forceをつければ)容赦なく削除します。つまり、うっかり変更をコミットし忘れた状態でcleanupすると、その変更は永久に失われます。
worktree-cleanupスキルでは、この事故を防ぐための安全チェックを実装しています。
check_uncommitted_changes() {
if [ "$(git status --porcelain)" != "" ]; then
if [ "$FORCE" = false ]; then
log_error "You have uncommitted changes"
git status --short
log_info "Please commit or stash your changes before cleaning up"
exit 1
fi
fi
}
未コミットの変更がある場合は、エラーメッセージとともに変更ファイルの一覧を表示し、処理を中断します。--forceフラグを明示的に指定しない限り、変更が消失することはありません。
worktree環境の検証
もう一つの安全策として、現在のディレクトリがworktree内であることを確認する処理も入れています。
GIT_DIR=$(git rev-parse --git-dir)
if [[ ! "$GIT_DIR" =~ \.git/worktrees/ ]]; then
log_error "Not in a worktree directory"
exit 1
fi
メインリポジトリでうっかりcleanupを実行してしまう事故を防ぎます。git rev-parse --git-dirの出力に.git/worktrees/が含まれているかどうかで、worktree内かどうかを判定しています。
ブランチ保持の設計判断
cleanup時にブランチも一緒に削除するかどうかは、悩ましいポイントです。僕の設計では、ブランチは削除せず保持する方針にしています。
理由は、PR作成→レビュー→マージというフローを壊さないためです。worktreeを削除しても、ブランチとそのPRは残り続けます。レビューが完了してマージされた後に、ブランチを削除すればよいのです。
推奨フローは以下の通りです。
- worktree内で実装を完了し、PRを作成する
- worktree-cleanupでworktreeを削除する(ブランチは残る)
- PRがマージされたら、ブランチを削除する
完全なソースコードはGitHub: worktree-cleanupで公開しています。
実際の運用フロー
ここまでの仕組みを使って、僕がレシピクリッププロジェクトでどのように開発しているか、典型的な1日のフローを紹介します。
朝: feature-Aの実装に着手します。create-worktree feature-aでworktreeを作成し、そのディレクトリでClaude Codeセッションを起動。実装を進めます。
昼前: feature-Aの実装が完了。PR作成してレビューに出します。ここで従来なら「待ち」が発生するところですが、すかさずcreate-worktree feature-bで次のworktreeを作成。feature-Bの実装に取りかかります。
午後: feature-Bを実装中に、feature-AのPRにレビューコメントが到着。ターミナルで.worktrees/feature-aにcdするだけで、feature-Aの作業環境に戻れます。Claude Codeのセッションもそのまま残っているので、コンテキストを失うことなくレビュー対応が可能です。
夕方: feature-Aの修正が完了し、re-requestしたらfeature-Aのworktreeをcleanup。feature-Bの作業に戻り、引き続き実装を進めます。
この流れを図にすると、以下のようになります。
ポイントは、どの時点でも「待ち」が発生しないことです。レビュー待ちの間は別の機能を実装し、レビューコメントが来たらすぐに対応できる。この並列性こそが、worktree × Claude Codeの真価です。
並列数と体感の変化
僕の経験では、並列開発の効果は2つ目のworktreeを作った時点で劇的に現れます。1つ目の作業がブロックされている間に、2つ目の作業を進められるだけで、1日の生産量が体感で1.5倍以上になります。
3つ目のworktreeを追加すると、さらに「常に何か進んでいる」状態が維持できるようになります。ただし、4つ以上になるとコンテキストの切り替えコストが無視できなくなり、「今どの機能を実装していたか」を思い出す時間が発生します。
僕のスイートスポットは、実装中2つ + レビュー待ち1つ = 合計3つです。この構成なら、常にアクティブな作業が1つ以上ある状態を維持しつつ、認知負荷を適切な範囲に抑えられます。
トラブルシューティングとTips
よくあるエラー早見表
実運用で遭遇しやすいエラーと対処法をまとめました。
| エラー | 原因 | 対処法 |
|---|---|---|
fatal: 'xxx' is already checked out |
同じブランチが別worktreeで使用中 |
git worktree list で確認し重複を解消 |
| ポート競合 | 複数worktreeで同じポートを使用 | create-worktreeのポートランダム化で自動回避 |
node_modules の不整合 |
worktree作成後にインストール漏れ |
make setup の自動実行で解消 |
| 未コミット変更の消失 | cleanup時の確認漏れ | worktree-cleanupの安全チェックで防止 |
| worktree内でgit操作がおかしい | .gitディレクトリの参照問題 |
git worktree repair で修復 |
特に最初のエラーは、worktreeを使い始めた直後によく遭遇します。Gitは同じブランチを複数のworktreeで同時にチェックアウトすることを許可しないため、このエラーが出た場合はgit worktree listで既存のworktreeを確認してください。
運用Tips
実践を通じて得られた知見をいくつか共有します。
同時worktreeは3〜4個まで。それ以上はマシンリソース(メモリ、CPU)との兼ね合いで、dev serverの動作が不安定になりがちです。特にNode.jsのdev serverは1つあたりの消費メモリが大きいため、マシンスペックに応じて調整してください。
Claude Codeセッションに説明的な名前をつける。複数のworktreeでClaude Codeを起動していると、どのセッションがどの機能に対応しているか分からなくなります。Claude Codeの/resumeコマンドでセッションを再開する際に、名前があると見つけやすくなります。
CLAUDE.mdにworktree運用ルールを記載しておく。Claude Codeはセッション開始時にCLAUDE.mdを読み込むため、worktreeの構成や運用ルールを書いておくと、各セッションで一貫した振る舞いが期待できます。
.worktrees/を.gitignoreに追加する。これを忘れると、worktreeのディレクトリがGitの追跡対象になってしまいます。リポジトリをセットアップしたら、最初に追加しておきましょう。
実際にハマった失敗談
最後に、僕が実際に経験した失敗を共有します。
失敗1: worktreeの存在を忘れてブランチを削除しようとした
PRがマージされた後、git branch -d feature/xxxでブランチを削除しようとしたところ、「ブランチは別のworktreeでチェックアウトされています」というエラーが出ました。worktreeのcleanupを忘れていたのです。先にworktreeを削除してからブランチを削除する、という順序を守る必要があります。
失敗2: メインリポジトリでgit pullしたら全worktreeに影響した
当然といえば当然ですが、.gitのオブジェクトデータベースは共有されているため、メインリポジトリでgit pullすると、その変更はすべてのworktreeから参照可能になります。これ自体は問題ありませんが、worktree内でのrebaseが必要になるケースがあり、最初は戸惑いました。各worktreeでgit rebase mainを実行すれば同期できます。
失敗3: .envの更新をworktreeに反映し忘れた
メインリポジトリの.envに新しい環境変数を追加した後、既存のworktreeにはその変更が自動的には反映されません。create-worktreeは作成時にコピーするだけなので、後から追加された変数は手動で同期する必要があります。これは今後の改善課題です。
まとめ
PRレビュー待ちの「空白時間」を解消したい──その一心で始めたgit worktreeとClaude Codeの組み合わせは、僕の開発体験を根本から変えました。
ブランチ切り替えのたびに環境を再構築する苦痛から解放され、Claude Codeのコンテキストを失う心配もなくなりました。Anthropic公式が「the single biggest productivity unlock」と位置づけるのも納得です。worktreeが提供する「物理的に独立した作業空間」は、Claude Codeの「セッション内コンテキスト維持」と完璧に噛み合います。
自動化スキル(create-worktreeとworktree-cleanup)を整備すれば、ポート競合や環境ファイルの管理といった煩わしさからも解放されます。並列開発のハードルは、思っている以上に低いのです。
まずは git worktree add .worktrees/試したい機能 -b feature/試したい機能 main から始めてみてください。cd .worktrees/試したい機能でそのディレクトリに移動し、Claude Codeを起動する。たったこれだけで、並列開発の世界への第一歩が踏み出せます。
今回紹介した自動化スキルは、以下のリポジトリで公開しています。ぜひ活用してみてください。