雰囲気で理解する Git Worktree
1日目はほげさんの「記事を書いてみると感じる "いいこと"」記事でした。
記事だけに限らず僕達は日常的に考えをまとめて誰かに発信していると思います。
僕も文章を作るのは得意ではないですが、フィードバックをもらい続けてるうちにある時にどういう時に自分がよく指摘されているのかに気づけるようになりました。
そこに気づけたら後は対策していくだけなので簡単!
ここを改善すれば自分は成長できるんだーって思えるかどうかはモチベを保つために個人的に大切にしてるところです。
はじめに
今年もAI関連のネタを書いていきます!
なぜGit Worktreeというテーマを取り上げたかというと、AIエージェントを用いた開発をしていて効率化を考えた際に「並列実装をもっとスムーズに進められないか」と思ったからです。
このテクニックについて中々深堀りするタイミングが取れてなかったのでせっかく勉強するならアドベントカレンダーに投稿しようと思ったのが始まりです。
記事は3部構成で考えています。
- Git Worktreeについて知る
- tmuxについて知る
- Git Worktreeとtmuxを組み合わせて並列実装をどのように実現するのか
新しいことを学ぶ時は分解した方が理解しやすいので、テーマごとに分けています。
今回はその1部として「Git Worktreeについて知る」をお届けします。
この記事では細かいコマンドの解説はしません。
Git Worktree について解説する記事は山ほどあるため、網羅的なコマンド解説はしませんが、概念理解に必要なコマンドは紹介します
この記事では概念的な理解してもらい、なんとなくのイメージを掴んでもらうことを目指しました。
では早速本題に移ります。
Git Worktreeって何?
「1つのGitリポジトリから、同時に複数の作業ディレクトリ(フォルダ)を生やし、それぞれで異なるブランチの作業を並行して行える機能」 です。
一言で言うと、あなたの開発環境に「作業机(サイドデスク)を瞬時に増設する機能」 ぐらいの認識で大丈夫です。

画像のように作業机が増えるんだなーくらいの認識でOK
とりあえずGit Worktree は 作業中に割り込みタスクが入った際に使うものなんだなーぐらいの理解で問題ありません。
割り込みタスクがあった時にしたいことは何でしょう?
作業途中のコードをどこか一時退避させたいと思います。
そのような時あなたならどうしますか?
一時退避に使うテクニック
あまり深く気にしたことがなかったので改めて調べてみました。
Git Stash
Git Stash といえば 作業を一時退避させる時に使う定番のテクニックです。
私はほぼこれを使います。
Git Stashは現在の作業状態を一時的に保存(=スタッシュ)して、 clean な状態の作業ディレクトリに戻すことができます。
後でそのスタッシュを復元すれば、以前の作業をそのまま再開できます。

机の上にあるものをとりあえずダンボールに入れる
コマンドはシンプルで、以下の通りです。
git stash push -m "一時保存: 機能Aの途中"
必要なタイミングで復元するには以下のコマンドを使います。
git stash apply stash@{0}
ただし、複数のタスクが並行で発生するとスタッシュの管理が煩雑になりがちです。名前をつけて管理しても、コンフリクトの解消で混乱することが多々あります。
たまにですがコンフリクト解消に失敗して余計な工数が発生してしまうことがありました。
新しいブランチを切り、コミットしてから切り替える
作業中の変更を適当なメッセージでコミットし、いったん履歴に残す形でブランチを切り替える方法です。
新しいブランチを切って作業してるときは 例のように wip コミットで逃がすみたいなことはよくします。
git add .
git commit -m "wip: 機能Aの途中"
git checkout hotfix/login-error
後で戻ってきて、git rebase -i などで WIP コミットを整理します。
別ディレクトリにリポジトリを再クローンする
別のフォルダに同じリポジトリをクローンし、そこで別のブランチを扱うという方法です。
git clone . ../my-repo-hotfix
cd ../my-repo-hotfix
git checkout hotfix/db-connection
これなら作業ブランチと割り込みタスクが完全に分離できる一方、ディスク容量の無駄や、設定・ツールの再構築が面倒というデメリットがあります。
こんな面倒なことをする人はいないと思いますが一応選択肢として挙げました。
Git Worktree を使う
上記の手順で発生していた課題を解消してくれるのが、まさにこの Git Worktree です!
リモートクローン不要、スタッシュ不要、WIPコミットも不要。
ひとつのリポジトリから、別の作業ディレクトリを生成し、そこで別のブランチを切り出して作業ができるようになります。
別のフォルダにいるかのように別のブランチが扱える上に .git は共有されているため、無駄なディスク容量も使わないといった便利な手法です。
次のセクションでGit Worktreeの具体的な使い方を見ていきましょう。
Git Worktree の具体的な使い方
では、実際に手を動かしてみましょう。
ここでは以下のような、よくある Node.js プロジェクトを例にします。
例: 元のリポジトリ構成
my-app/
├─ .git/
├─ src/
│ └─ index.ts
├─ package.json
├─ tsconfig.json
└─ README.md
現在いる my-app ディレクトリから、割り込み用のブランチ hotfix/login-error を扱う新しい作業ディレクトリ ../my-app-hotfix を作成します。
1. Worktree を追加する
まずは Worktree を追加します。
# git worktree add <作業ディレクトリのパス> <ブランチ名 or チェックアウトしたいコミット>
git worktree add ../my-app-hotfix hotfix/login-error
これで、../my-app-hotfix という新しい作業ディレクトリが作成されます。
ファイルシステム上には、以下のように2つの作業フォルダが並ぶ状態になります。
-
my-app… これまでの作業ディレクトリ -
my-app-hotfix… 新しく生えた作業ディレクトリ(hotfix/login-errorブランチ用)
追加後のディレクトリ構成
コマンド実行後の全体構成はこうなります。
my-app/
├─ .git/
│ ├─ worktrees/
│ │ └─ my-app-hotfix/
│ │ ├─ HEAD
│ │ ├─ config
│ │ ├─ index
│ │ └─ logs/
│ │ └─ HEAD
│ └─ ...(省略)
├─ src/
│ └─ index.ts
├─ package.json
├─ tsconfig.json
└─ README.md
my-app-hotfix/
├─ .git # ← ファイル(元リポジトリ .git へのポインタ)
├─ src/
│ └─ index.ts
├─ package.json
├─ tsconfig.json
└─ README.md
2. Worktree の確認(リスト)
現在、どの Worktree が有効になっているか、どこに存在するかを一覧で確認できます。
git worktree list
/Users/Projects/my-app 8f8d689 [feature/main-task]
/Users/Projects/my-app-hotfix 8b4e72c [hotfix/login-error]
3. Worktree のクリーンアップ(削除)
Worktree ディレクトリでの作業が完了したら、後片付けをしましょう。
ブランチをマージまたは削除した後に Worktree を削除します。
作業ディレクトリがわからない場合は git worktree list で確認しましょう。
# Worktree の作業ディレクトリを削除
git worktree remove /Users/Projects/my-app-hotfix
ここからは Worktree の仕組みの話になります。長いので興味がなければ飛ばしてください。
Worktree を触って気付いた点
git worktree add コマンドのポイントは、以下の2点です。
- 新しい作業ディレクトリ(ワーキングツリー)が増える
- Git リポジトリ本体(.gitデータ)は増えない
表現を変えると、「作業机(ワーキングツリー)だけ増えるが、引き出しの中身(履歴やオブジェクト)は共通」という状態になっています。
これにより、ディスク容量の無駄なく、複数のブランチを同時に、独立した環境で作業できるのです。
.git が「ディレクトリではなくファイル」になっている
新しく作成された Worktree 側のフォルダ(例: my-app-hotfix)を見ると、.git がディレクトリではなく、単なるテキストファイルになっていることに気がつきます。
この .git ファイルの中身は、単に元のリポジトリ内のパスを指し示すポインタとして機能しています。
↓ Worktree 配下にある .gitの中身
gitdir: <absolute_path>/my-app/.git/worktrees/my-app-hotfix
- Git の本体(オブジェクトデータベースなど)は元の
my-app/.git/側にある - Worktree ごとのメタ情報(HEADやindexなど)は
my-app/.git/worktrees/◯◯にまとめて置かれている
このポインタの仕組みによって、すべての Worktree がたった一つのリポジトリ本体を共有しながら動作しています。
この仕組みのおかげでリポジトリを別々に clone しなくて済んでるということがわかりました。
Worktree で管理している情報
新しく追加した Worktree の中と元のディレクトリの中にあるファイルに差分があって気になって調べました。
✔ 共有されるもの(リポジトリ本体の情報)
これらはすべて元のリポジトリ(my-app/.git/)に置かれ、Worktree 間で共同で使われます。
- コミット履歴とGit オブジェクト(履歴の実体)
- ブランチやタグの参照(refs)
- リモート設定(
originなど)
✖ 独立しているもの(作業ごとの状態)
これらは Worktree ごとに独立しているため、並行作業を可能にします。
- ワーキングツリー(実際のファイルの内容)
-
インデックス(
git addしたステージングの状態) - HEAD(どのブランチ / コミットを指しているか)
- 作業中の未コミット変更と未追跡ファイル
Git Worktree が役立つユースケース
最初に一時退避の例を出しちゃったんですが、Worktree は作業の一時退避に特化した機能ではありません。
ここまでの説明で 「作業の分離」 が出来るという特徴がある事が、なんとなく伝わったかと思います。
改めてどういう時に使えるかを考えて見ました。
1. 並行した作業と実装ができる
メインの Worktree で大規模なタスクを進めつつ、別の Worktree で並行して緊急性の低い別のタスク(例: ドキュメント修正)をコミットまで完了させることができます。
AIエージェントに機能Aを開発させつつ、人間が機能Bを並行して実装する際、Worktree を利用することで、Gitの操作やコンフリクトを気にせず並列で作業を進める環境を簡単に構築できます。
AIエージェントを組み合わせた開発については別の記事で触れますのでお楽しみに!
2. ブランチ間の動作確認が効率的にできる
ライブラリのバージョンアップ対応をしていたとします。
Worktree を知らない私は 作業途中のブランチをstash して再度ライブラリをインストールし直して、ビルドを行っていました。
この作業が地味ながら手間に感じていました。
Worktree を使えば、各ディレクトリがそれぞれのブランチの依存関係やビルド成果物を完全に分離して保持できるため、この再ビルド・再インストール地獄から解放されるわけです。
まとめ
- Worktree は、一つの Git リポジトリから複数の独立した作業ディレクトリを生やす機能
- 「履歴(オブジェクト)は共有し、作業状態(ワーキングツリー、インデックス、HEAD)は分離する」という仕組みが、並行作業を可能にする
最後に
今回の記事で、Git Worktree を使うと、git clone や git stash なしで作業の分離が出来ることを知りました。
しかし、ここで新しい課題が生まれました!
Worktree によって、あなたは同時に複数のプロジェクト(my-app と my-app-hotfix など)で作業できるようになりました。
これはつまり、「複数のターミナルウィンドウやタブ」 を同時に開き、それぞれでビルドやテストの実行、ログ監視などを行う必要があるということです。
「今、どのターミナルがどの Worktree(ブランチ)にいるんだっけ?」
「ログを流しながら、別の画面でコードを編集したいのに、ウィンドウの切り替えが面倒だ...」
Worktree が増えるほど、このターミナルの管理の煩雑さは増していきます。
この**「増えた作業机(Worktree)を、いかに快適かつシームレスに使いこなすか」**という課題を解決するのが、ターミナルマルチプレクサである tmux です。
第2部では、この Worktree 環境を瞬時に切り替え、複数の作業セッションを一つのウィンドウ内でシームレスに管理する際によく使われている tmux について深掘りします。
お楽しみに!
3日目は弊社のmari による「NotebookLMを使ってドキュメントを読みやすくする」です。
Discussion