git worktreeで複数ブランチを同時に扱ってみる
経緯
最近、CursorやClaude CodeなどのAIコーディングツールが、並列タスク実行のために git worktree を活用しているという話題を目にしました。
従来の開発では、急な本番バグ対応が入った際に、作業中のfeatureブランチを一旦コミットまたはstashして、mainブランチに切り替える必要がありました。しかし、git worktree を使えば、ブランチを切り替えることなく、別のディレクトリで並行して作業することが可能です。
この記事では、git worktree の概要と実際の使い方、そしてディレクトリ構造の変化について詳しく解説していきます。
git worktreeとは
git worktree は、1つのGitリポジトリで複数の作業ディレクトリ(ワークツリー)を管理するためのコマンドです。
通常、1つのリポジトリには**1つの作業ツリー(ワーキングディレクトリ)**しか持てません。ブランチを切り替えるには git checkout や git switch を使い、作業ディレクトリ内のファイルが書き換わります。
しかし、git worktree を使うと、同じリポジトリの異なるブランチを複数のディレクトリで同時にチェックアウトが可能になります。
メリット
- ブランチ切り替え不要: mainブランチで開発中のコードを維持しつつ、別ディレクトリでfeature-xブランチを同時に作業
- 並列作業が可能: 複数のタスクを同時進行できる
- ビルド環境の維持: 開発サーバーを起動したまま、別ブランチで作業できる
- stash不要: 作業途中のコードをstashせずに別ブランチへ移動できる
仕組み(図解)
すべてのワークツリーは、同じ .git ディレクトリを共有しています。そのため、どのワークツリーでコミットしても、同じリポジトリの履歴に反映されます。
どのようなときに使うか - 実践的な活用方法
ケース1: 緊急バグ修正が入った場合
開発中のfeatureブランチで作業していたところ、本番環境で緊急のバグが発覚。すぐにhotfixブランチで対応する必要がある場合:
従来の方法:
# 作業中の変更をstash
git stash
# mainブランチに切り替え
git checkout main
# hotfixブランチを作成
git checkout -b hotfix/critical-bug
# 修正作業...
# 修正完了後、元のブランチに戻る
git checkout feature/new-feature
git stash pop
git worktreeを使う方法:
# 現在のディレクトリはそのまま(feature/new-featureで作業継続可能)
# worktree配下にhotfixブランチを作成
git worktree add worktree/hotfix-critical-bug -b hotfix/critical-bug main
# 別ターミナルまたはエディタで hotfix-critical-bug ディレクトリを開いて作業
cd worktree/hotfix-critical-bug
# 修正作業...
git add .
git commit -m "Fix critical bug"
git push origin hotfix/critical-bug
# 作業完了後、元のディレクトリに戻る
cd ../../
# hotfix用のワークツリーを削除
git worktree remove worktree/hotfix-critical-bug
ケース2: レビュー中に別の作業をする
プルリクエストのレビュー待ち中に、別のfeatureを開発したい場合:
# 現在: feature/login ブランチで作業中、PRを出してレビュー待ち
# 新しいfeatureブランチ用のワークツリーを追加
git worktree add worktree/feature-dashboard -b feature/dashboard main
# ディレクトリ構造:
# my-project/ (メインのワークツリー)
# my-project/worktree/feature-dashboard/ (追加のワークツリー)
# 新しいワークツリーで作業開始
cd worktree/feature-dashboard
# 開発作業...
ケース3: 異なるバージョンのビルドを同時実行
開発サーバーを起動しながら、別バージョンでビルドやテストを実行したい場合:
# メインディレクトリで開発サーバーを起動(localhost:3000)
npm run dev
# 別ブランチでE2Eテストを実行
git worktree add worktree/test-branch feature/e2e-test
cd worktree/test-branch
npm install # 必要に応じて依存関係をインストール
npm run test:e2e
実際のコマンドの活用方法とディレクトリの変化
ここでは、実際にコマンドを実行したときのディレクトリ構造の変化を詳しく見ていきます。
初期状態
my-project/
├── .git/
├── src/
├── package.json
└── README.md
現在のブランチ: main
1. 新しいワークツリーを追加
cd my-project
git worktree add worktree/feature-login -b feature/login
コマンドの意味:
-
worktree/feature-login: 新しいワークツリーを作成するパス(プロジェクトルートからの相対パス) -
-b feature/login: 新しいブランチfeature/loginを作成してチェックアウト - 最後の引数(省略可): 基点となるコミット(デフォルトはHEAD)
実行後のディレクトリ構造:
my-project/ ← メインのワークツリー (mainブランチ)
├── .git/ ← 実体のあるGitリポジトリ
│ ├── worktrees/ ← 追加ワークツリーの管理情報
│ │ └── feature-login/
│ │ ├── HEAD
│ │ ├── index
│ │ └── logs/
│ ├── objects/
│ └── refs/
├── worktree/ ← ワークツリー用ディレクトリ
│ └── feature-login/ ← 追加されたワークツリー (feature/loginブランチ)
│ ├── .git ← ファイル(シンボリックリンクではなくテキスト)
│ ├── src/
│ ├── package.json
│ └── README.md
├── src/
├── package.json
└── README.md
重要なポイント:
-
worktree/feature-login/.gitはディレクトリではなくファイルです - このファイルの中身は:
gitdir: /path/to/my-project/.git/worktrees/feature-login - 実際のGit管理情報は
my-project/.git/worktrees/feature-login/に保存されます - すべてのワークツリーは同じ
.gitリポジトリを共有します
2. ワークツリーの一覧を確認
git worktree list
出力例:
/path/to/my-project abc1234 [main]
/path/to/my-project/worktree/feature-login def5678 [feature/login]
各行の意味:
- 1列目: ワークツリーのパス
- 2列目: 現在のコミットハッシュ
- 3列目: チェックアウトされているブランチ
3. 既存のブランチをチェックアウト
リモートに既に存在するブランチをワークツリーとして追加する場合:
# リモートブランチを取得
git fetch origin
# 既存のブランチをチェックアウト(-bオプションなし)
git worktree add worktree/bugfix-header bugfix/header
これで bugfix/header ブランチが新しいワークツリーとしてチェックアウトされます。
4. ワークツリーで作業する
cd worktree/feature-login
# 通常のGit操作が可能
git status
git add .
git commit -m "Add login feature"
git push origin feature/login
ディレクトリ内での作業:
-
worktree/feature-loginディレクトリ内では、feature/loginブランチの状態でファイルが展開されています - コミット、プッシュ、プル、ブランチ切り替えなど、通常のGit操作がすべて可能
- メインディレクトリ(
my-project)とは独立して作業できます
5. ワークツリーを削除
作業が完了したら、ワークツリーを削除します。
# 方法1: ディレクトリごと削除
git worktree remove worktree/feature-login
# 方法2: ディレクトリを手動で削除してから
rm -rf worktree/feature-login
git worktree prune # メタデータをクリーンアップ
削除後のディレクトリ構造:
my-project/ ← メインのワークツリーのみ残る
├── .git/
│ └── worktrees/ ← feature-loginのメタデータも削除される
├── worktree/ ← 空のディレクトリ(必要なら削除可能)
├── src/
├── package.json
└── README.md
6. 古いワークツリーのメタデータをクリーンアップ
ワークツリーのディレクトリを手動で削除した場合、.git/worktrees/ 内にメタデータが残ることがあります。
git worktree prune
これにより、実際には存在しないワークツリーの管理情報が削除されます。
よく使うコマンド一覧
# 新規ブランチを作成してワークツリーを追加
git worktree add <path> -b <new-branch>
# 既存のブランチをワークツリーとして追加
git worktree add <path> <existing-branch>
# 現在のブランチと同じコミットでワークツリーを追加(detached HEAD)
git worktree add <path>
# ワークツリー一覧を表示
git worktree list
# ワークツリーを削除
git worktree remove <path>
# 削除されたワークツリーのメタデータをクリーンアップ
git worktree prune
# ワークツリーを別の場所に移動
git worktree move <old-path> <new-path>
# ワークツリーをロック(削除されないようにする)
git worktree lock <path>
# ロックを解除
git worktree unlock <path>
まとめ
主な利点:
- ブランチ切り替えやstashが不要になり、作業効率が向上
- 緊急対応と通常開発を並行して進められる
- 開発サーバーやビルド環境を維持したまま別ブランチで作業可能
- 複数のタスクをシームレスに切り替えられる
注意点:
- 同じブランチを複数のワークツリーで同時にチェックアウトすることはできない
-
ワークツリー用ディレクトリを
.gitignoreに追加することを推奨:worktree/をリポジトリに含めないため、.gitignoreに以下を追記してください# Git worktree用ディレクトリ worktree/
Appendix
開発環境での注意
開発環境で気をつけたい点をまとめます。
特に Node.js/npm プロジェクトでは、ワークツリーごとに依存関係(node_modules/)を用意する必要があるため、ワークツリーを追加するたびに npm install が必要になります。結果として次の問題が起こり得ます。
- インストール時間の増加: ワークツリー毎にパッケージを入れると、合計で数分〜数十分の待ち時間が積み重なります。
- ディスク使用量の増大: 1ワークツリーあたり数百MB〜数GBを消費することがあり、複数作成すると急速に容量を圧迫します。
試して有効だった対策を紹介します。
- pnpm を使う
# グローバルなストアを使ってインストールを高速化
pnpm install
-
pnpmは.pnpm-storeにパッケージを集約し、各ワークツリーにはハードリンクを作るため、ディスクを節約できます。 - npm より高速にインストールできることが多いです。
node_modulesを共有する(シンボリックリンク)
# 例: worktree/feature-login からメインの node_modules を参照する
cd worktree/feature-login
ln -s ../../node_modules node_modules
- ブランチ間で依存バージョンが異なると問題になるため、同じ依存関係を使うワークツリーに限定して使ってください。
npm ciを使う
# package-lock.json に基づき素早くクリーンなインストールを行う
npm ci
-
npm installより高速で再現性の高いインストールができます。
プロジェクトの規模や運用方針に合わせて、上記のいずれか(または組み合わせ)を選ぶと作業が快適になります。
AIツールとの連携や、複雑なプロジェクトでの並行開発において、git worktree は強力な武器となります。ぜひ実際のプロジェクトで試してみてください。
Discussion