急ぎの修正依頼が来たとき、手元のブランチは編集の途中。定番の対処は、stash、中途半端なコミット、もう1つのcloneの三択です。
git worktreeとは、1つのGitリポジトリに複数の作業ディレクトリを紐づけ、ブランチごとに別のフォルダで同時に開いておける機能です。
ただし、追加した側のフォルダを覗くと、.gitがディレクトリではなくファイルになっています。
履歴を共有しているのに、なぜブランチごとに独立して動くのか。手元で動かした出力を見ながら、その仕組みを順にたどります。
この記事でわかること
- git worktreeとは何か(1つのリポジトリで複数ブランチを同時に開く機能)
.gitがファイルになる仕組みと、共有される情報と独立する情報- cloneやstash、checkoutとの違い
- Claude Codeの並列実行で使うときの落とし穴(未コミットの変更は持ち越されない)
PARTS LIST /目次
git worktreeとは?1つのリポジトリで複数ブランチを開く機能
git worktreeは、Git 2.5(2015年7月)で追加された標準機能です。追加のインストールは要りません。
Gitでは、作業ファイルが並ぶフォルダをworktree(作業ツリー)と呼びます。リポジトリを作ると最初の1つが自動でできていて、これをmain worktreeと呼びます。
git worktreeは、このフォルダをあとから何個でも増やす仕組みです。
通常のGitは作業ディレクトリが1つだけ
git initやgit cloneで作られるフォルダは1つです。ブランチを切り替えるたびに、そのフォルダの中身がまるごと入れ替わります。
作業途中のファイルがあると、checkoutは変更の衝突で止まるか、変更を抱えたまま切り替わります。
だから割り込みの修正が入ると、stash、仮コミット、もう1つのcloneのどれかを選ぶことになります。
app/:main → feature-a → hotfix切り替えるたびに、同じフォルダの中身が入れ替わる。
app/:mainapp-feature-a/:feature-aapp-hotfix/:hotfix切り替えず、フォルダを移動するだけ。
worktreeで解決できる3つの場面
worktreeのメリットは、今の作業を止めずに済むことです。効くのは、次の3つの場面です。
- 緊急の修正:作業中のブランチはそのまま置いて、別フォルダでhotfixを書く
- レビュー:相手のブランチを別フォルダで開き、動かしながら確認する
- 長い処理の待ち時間:ビルドやテストを回している間に、別のブランチで作業を進める
git worktree add ../app-hotfix -b hotfix
git worktree list
1行目で、隣のフォルダapp-hotfixに新しいブランチhotfixを作って開きます。2行目で、いま存在するworktreeの一覧を確認できます。
git worktreeの仕組み|.gitファイルと共有の境界
worktreeが別フォルダで別ブランチを動かせる原理は、リポジトリの中身を「全員で共有する部分」と「フォルダごとに持つ部分」に分けている点にあります。
共有するのはオブジェクトとブランチ、独立して持つのはHEADとindex。この境界は、.gitの中を見るとはっきりわかります。
app-feature-a/.git(ファイル).git/worktrees/app-feature-a/HEAD、index、gitdir、commondir.git/ 本体objects、refs、configapp/.git(ディレクトリ)main worktreeとlinked worktreeの違い
最初からある作業ディレクトリがmain worktree、git worktree addで追加したものがlinked worktreeです。
リポジトリの本体である.gitディレクトリを持つのは、main worktreeだけです。
.gitがファイルになり.git/worktrees/を指す
linked worktreeの.gitを開くと、ディレクトリではなく1行だけのテキストファイルです。Git 2.50.1(Apple Git)で実際に作って確認しました。
$ cat ../app-feature-a/.git
gitdir: /path/to/app/.git/worktrees/app-feature-a
指す先の.git/worktrees/app-feature-a/には、このworktree専用の情報が入っています。
$ ls .git/worktrees/app-feature-a
HEAD ORIG_HEAD commondir gitdir index logs refs
$ cat .git/worktrees/app-feature-a/HEAD
ref: refs/heads/feature-a
$ cat .git/worktrees/app-feature-a/commondir
../..
ここにobjectsはありません。commondirの../..が、共有側の本体である.git/へ戻る道です。
linked worktreeの中でgit rev-parseを実行すると、この2つの場所が別々に返ります。
$ git rev-parse --git-dir --git-common-dir
/path/to/app/.git/worktrees/app-feature-a
/path/to/app/.git
前者がworktree専用の置き場、後者が全員で共有する置き場です。これが「履歴は共有、状態は独立」の正体です。
共有されるものと独立するもの
公式ドキュメントの分類を、手元の挙動と突き合わせて、図と表にします。
app/独立:作業ファイル独立:HEAD → main
独立:index
app-feature-a/独立:作業ファイル独立:HEAD → feature-a
独立:index
.git/オブジェクトDB(コミットとファイルの中身)refs/heads/*、refs/tags/*(ブランチとタグ)
config(リモートなどの設定)
ブランチ名の一覧は共有です。別のworktreeで開いているブランチには、git branchの一覧で+が付きます。
$ git -C ../app-feature-a branch --list
* feature-a
feature-b
+ main
git add編集して add。変わるのは app-feature-a/ の index だけ。git commitコミットC2は共有の objects に入り、refs/heads/feature-a がC2へ進む。git branch -vapp/ からも feature-a がC2へ進んだのが見える。app/ の HEAD(main)と index は変わらない。同じブランチを2か所で開けない理由
すでに開いているブランチを別のworktreeで開こうとすると、Gitは拒否します。
$ git worktree add ../dup main
Preparing worktree (checking out 'main')
fatal: 'main' is already used by worktree at '/path/to/app'
理由は、ブランチの先端が共有なのに、HEADとindexがworktreeごとに独立しているからです。
片方でコミットするとブランチが進み、もう片方のindexと作業ファイルは古いままになります。その状態でコミットすると、直前の変更を巻き戻してしまいます。
--forceで回避できますが、この状態を意図して作る場面は通常ありません。
ブランチを占有せずに同じコミットを開きたいときは、git worktree add --detach ../app-tmp mainのようにdetached HEADで開きます。この形なら、mainが別のworktreeで使用中でも拒否されません。
cloneやstash、checkoutとの違い
worktreeは、clone、stash、checkoutの間を埋める道具です。何が同じで何が違うのかを、表にまとめます。
選ぶ基準は2つあります。未コミットの変更を手放せるか、履歴を重複させたくないか、です。
cloneより軽い理由
cloneは.gitを丸ごと複製するため、履歴が大きいほどディスクも時間も使います。worktreeは作業ファイルだけを増やし、履歴は1つを共有します。
app/:.git/(履歴すべて)app-copy/:.git/(履歴すべて)fetchも、フォルダごとに行う。
app/:.git/(履歴すべて)app-feature-a/:.git は1行のファイルで、app/ の .git/ を指すfetchは1か所で、全フォルダに反映される。
cloneは別のリポジトリ扱いなので、fetchやブランチの更新も個別に行う必要があります。worktreeなら、1か所でfetchすれば全員に反映されます。
stashやcheckoutでは足りない場面
- stashの戻し忘れで、退避した作業が行方不明になる
- 切り替えのたびにビルド成果物や依存関係が入れ替わり、再ビルドが走る
- 2つのブランチの動作を、並べて比べられない
数分で終わる割り込みならstashで足ります。フォルダを分ける価値が出るのは、切り替えの回数が増えたときです。
Claude Codeの並列実行とworktree
AIエージェントに複数のタスクを同時に任せると、同じフォルダを2つのセッションが書き換えて衝突します。worktreeは、この衝突をフォルダを分けることで避ける手段です。
Claude Codeには、並列実行の土台としてworktreeが組み込まれています。
AIエージェントと相性がよい理由
セッションごとに作業フォルダとブランチが独立するため、ファイル編集が互いに触れ合いません。履歴は共有なので、作業が終わったあとにマージして統合できます。
claude --worktree feature-auth
公式ドキュメントによると、このコマンドは.claude/worktrees/feature-auth/にworktreeを作り、ブランチ名はworktree-feature-authになります。
サブエージェントも、isolation: worktreeを指定すれば専用のworktreeで動きます。
サブエージェントそのものの使い方は、Claude Codeサブエージェントの使い方にまとめています。
複数セッションを並べる方法はtmuxで並列実行する方法、役割を分けたエージェントを走らせる方法はAgent Teamで専門家チームを作る実践ガイドで扱っています。
worktree内のセッションを再開する手順は、セッション再開ガイドが参考になります。
Claude Codeの導入から基本操作までは、【2026年版】Claude Code使い方|導入から実践活用までが入口になります。
未コミットの変更は持ち越されない(私の失敗談)
worktreeは、コミット済みの内容から新しくチェックアウトされます。作業フォルダにある未コミットの変更は、コピーされません。この仕様で、ヒヤリとする経験をしました。
2026年9月7日、ブログ記事のリライトをClaude Codeのサブエージェントに任せたときの話です。
事前にWordPressから最新の本文を取得し、ローカルのHTMLを最新の状態に更新していました。ただし、このHTMLはgit管理下にあり、更新はコミット前でした。
サブエージェントをisolation: worktreeで起動したところ、作業の土台になったのは8月24日にコミットした古い本文です。
編集の途中で、サブエージェント自身が「本文の書き方が、取得済みの内容と食い違っている」と報告してきて、発覚しました。
実害は出ませんでした。WordPressへのアップロードが、環境の都合でたまたま失敗していたからです。アップロードが通っていたら、本番の記事が約2週間前の状態に巻き戻っていたことになります。
公式ドキュメントでは、新しいworktreeの土台は既定でリモートのデフォルトブランチ(通常はmain)とされています。設定worktree.baseRefを"head"にすると、手元のHEADに変わります。
どちらを選んでも、未コミットの変更は含まれません。
.claude/worktrees/名前/対策は単純で、worktreeを作る前に、必要な変更をコミットしておくことです。生成物や取得結果をgit管理下に置いている場合は、特に効きます。
git worktreeを使うときの注意点
新しく作ったworktreeは、コミット済みのファイルだけが並んだ、ほぼ新品のフォルダです。そう考えると、つまずきにくくなります。よくある落とし穴を2つ挙げます。
公式ドキュメントには、複数チェックアウトはまだ実験的な機能で、サブモジュール(submodule)を含むスーパープロジェクトでの利用は推奨されない、とも書かれています。
node_modulesや.envは引き継がれない
Gitで管理されていないファイルは、新しいworktreeに存在しません。node_modules、.env、ビルド成果物が該当します。依存関係のインストールは、worktreeごとにやり直します。
Claude Codeなら、プロジェクト直下の.worktreeincludeに.gitignore形式で書いたファイルを、新しいworktreeへコピーしてくれます。対象は、gitignore済みのファイルだけです。
.env
.env.local
フォルダを直接消すとpruneが必要になる
worktreeのフォルダをFinderやmvで動かしたり消したりすると、Git側の登録だけが残ります。実際に隣のフォルダへ移動してみると、一覧にprunableと出ました。
$ git worktree list
/path/to/app f000549 [main]
/path/to/app-feature-b f000549 [feature-b] prunable
$ git worktree prune -v
Removing worktrees/app-feature-b: gitdir file points to non-existent location
正規の手順はgit worktree removeです。未コミットの変更があると拒否され、--forceを付けたときだけ消せます。git worktree pruneは、登録だけ残った残骸を掃除するコマンドです。
フォルダを動かしたいときはgit worktree moveを使います。mvで動かしてしまった場合は、git worktree repairでGit側の登録を直せます。
手元では、mvの直後に一覧へprunableと出ましたが、repairを実行すると新しい場所で正常に表示されました。動かしたフォルダを残したいなら、pruneより先にrepairです。
git worktreeのよくある質問
git worktreeについて、検索でよく見かける疑問を、Q&A形式で7つにまとめました。
回答は、本文で実機確認した挙動と、GitおよびClaude Codeの公式ドキュメントの記述をもとにしています。仕組みの要点を確認したいときにも使えます。
Q1. git worktreeとは何ですか?
A1. 1つのGitリポジトリに複数の作業ディレクトリを紐づけ、ブランチごとに別のフォルダで同時に開ける機能です。履歴とブランチは共有し、HEADとindexはフォルダごとに独立します。
Q2. git worktreeとgit cloneの違いは何ですか?
A2. cloneは.gitを丸ごと複製して別のリポジトリを作ります。worktreeは履歴を1つ共有したまま、作業フォルダだけを増やします。履歴の重複がなく、fetchも1か所で済みます。
Q3. 同じブランチを複数のworktreeで開けますか?
A3. 通常は開けません。すでに別のworktreeで使われているブランチを指定すると、fatalエラーで拒否されます。--forceで回避できますが、HEADとindexが食い違うため、推奨されません。
Q4. worktreeを削除するにはどうしますか?
A4. git worktree removeを使います。未コミットの変更があると拒否され、--forceを付けると削除できます。フォルダを直接消した場合は、git worktree pruneで登録の残骸を掃除します。
Q5. 未コミットの変更は新しいworktreeに引き継がれますか?
A5. 引き継がれません。新しいworktreeはコミット済みの内容からチェックアウトされます。必要な変更は、worktreeを作る前にコミットしてください。
Q6. .envやnode_modulesはコピーされますか?
A6. Gitの標準動作ではコピーされません。依存関係はworktreeごとにインストールし直します。Claude Codeでは、.worktreeincludeに書いたgitignore済みファイルを新しいworktreeへコピーできます。
Q7. git worktreeはGitのどのバージョンから使えますか?
A7. Git 2.5(2015年7月)から使えます。現在の一般的なGitであれば、追加の設定なしで利用できます。
git worktreeの理解を整理する
急ぎの修正が来たときの三択に、4つ目の選択肢が加わります。仕組みの要点は次のとおりです。
- worktreeとは、1つのリポジトリに複数の作業ディレクトリを紐づける機能(Git 2.5以降)
- linked worktreeの
.gitはファイルで、.git/worktrees/名前/を指す - オブジェクト、ブランチ、設定は共有。HEADとindexはworktreeごとに独立
- 同じブランチは2か所で開けない
- 新しいworktreeは未コミットの変更を持たない。作る前にコミットし、依存関係や.envは別途用意する
次に割り込みの修正が飛んできたら、stashの前に、隣のフォルダを1つ増やしてみてください。
| REV. | DATE | 内容 |
|---|---|---|
| 2 | 2026-10-16 | 図解を描き直し(図面のデザインにそろえた) |
| 1 | 2026-09-22 | 初版 |


