徹底解説：git worktree の使い方


## はじめに

開発中に 「別ブランチの緊急修正を入れたい」「リリースブランチを長期間保持したい」――そんなときに `git checkout` で行ったり来たりすると作業ツリーが汚れ、衝突の温床になります。

Git 2.5（2015 年）で正式公開された **`git worktree`** を使えば、**1 つのリポジトリから複数の“作業ツリー（Worktree）”を生やし、各ツリーで別々のブランチを同時に操作**できます。

この記事では最新版 Git 2.45 時点での機能・落とし穴・実戦的なワークフローまで徹底解説します。

---

## 1. なぜ `git worktree` なのか

### 1‑1. 追加 clone と worktree の違い

```mermaid
flowchart TB
  subgraph Clone_Approach["追加 clone"]
    direction TB
    A1(".git/objects<br>100 % 複製") --> B1("作業ツリー #1")
    A2(".git/objects<br>100 % 複製") --> B2("作業ツリー #2")
  end

  subgraph Worktree_Approach["git worktree"]
    direction TB
    C1(".git/objects<br>共有") --> D1("作業ツリー #1")
    C1 --> D2("作業ツリー #2")
  end

  style Clone_Approach fill:#fdf5f5,stroke:#e88
  style Worktree_Approach fill:#f5fdf5,stroke:#8e8
```

| 方法           | ディスク容量          | フェッチ回数                       | オブジェクト整合性 |
| ------------ | --------------- | ---------------------------- | --------- |
| 追加 clone     | 100 % × clone 数 | clone ごと                     | 分断される     |
| **worktree** | **共有分のみ 1 コピー** | **1 度の `git fetch` で全ツリー反映** | 常に一貫      |

### 1‑2. 典型ユースケース

```mermaid
graph LR
  Hotfix(["緊急 Hotfix"]) -.->|別フォルダ| WT1("worktree: ../hotfix")
  Release(["長期リリース<br>branch"]) -.-> WT2("worktree: ../release-1.x")
  Review(["PR レビュー"]) -.-> WT3("worktree: ../pr‑1234")
  Sparse(["mono‑repo<br>+ sparse"]) -.-> WT4("worktree: ../sub‑module")
```

* **緊急修正**：現在の開発作業を汚さずに main から派生したワークツリーで修正 → マージ
* **リリース保守**：`release/X.Y` 用ワークツリーを常設し、パッチ適用を迅速化
* **コードレビュー／CI 再現**：Pull Request の HEAD をローカルでビルド・デバッグ
* **巨大 mono‑repo**：ワークツリーごとに `sparse-checkout` を変え、容量とビルド時間を削減

---

## 2. 基本文法と主要サブコマンド

| コマンド                                                  | 目的                            | 代表例                                                |
| ----------------------------------------------------- | ----------------------------- | -------------------------------------------------- |
| `git worktree add [-b <新ブランチ>] <path> [<commit-ish>]` | 作業ツリーを追加                      | `git worktree add -b hotfix ../hotfix origin/main` |
| `git worktree list [--porcelain]`                     | 既存ツリーの一覧                      | `git worktree list --porcelain`                    |
| `git worktree remove [--force] <path>`                | 作業ツリーを削除                      | `git worktree remove ../hotfix`                    |
| `git worktree prune`                                  | 存在しないツリー情報の掃除                 | `git worktree prune`                               |
| `git worktree lock [--reason <msg>]` / `unlock`       | 別メディア上ツリーの保護                  | `git worktree lock ../usb --reason "出張用"`          |
| `git worktree move <新パス>`                             | 物理フォルダを移動 (Git 2.17+)         | `git worktree move ../v2 ../archive/v2`            |
| `git worktree repair`                                 | `.git/worktrees` と実フォルダのずれを修復 | `git worktree repair`                              |

```mermaid
flowchart LR
  A["git worktree"] -->|create| B(add)
  A -->|inspect| C(list)
  A -->|delete| D(remove)
  A -->|cleanup| E(prune)
  A -->|move| F(move)
  A -->|lock| G(lock / unlock)
  A -->|repair| H(repair)
```

---

## 3. 5 分でわかる実践シナリオ

### 3‑1. 開発中に緊急 Hotfix が入った

```bash
# 1. 機能開発中 (feature/login)
$ git status            # まだコミット前の変更あり

# 2. Hotfix 用ワークツリーを作成
$ git worktree add -b hotfix-login ../hotfix-login origin/main

# 3. 作業ディレクトリを切り替え
$ cd ../hotfix-login
$ <修正を加えコミット>

# 4. main へマージし、CI が通ったらリリース
$ git checkout main
$ git merge --no-ff hotfix-login
```

```mermaid
sequenceDiagram
  participant Dev as 現在の作業ツリー (feature/login)
  participant Git as git worktree
  participant Hotfix as 新ワークツリー (hotfix-login)

  Dev->>Git: worktree add -b hotfix-login ../hotfix-login origin/main
  Git->>Hotfix: 作業ツリー生成
  Note over Hotfix: 修正をコミット
  Hotfix->>Git: merge → main
  Dev-->>Hotfix: 変更衝突なし
```

### 3‑2. リリースブランチを常駐させる

```bash
# リリース 1.x を別フォルダに常設しビルド検証に使う
git worktree add ../release-1.x origin/release/1.x --lock
```

---

## 4. メカニズムを掘り下げる

### 4‑1. `.git/worktrees` ディレクトリ構造

```mermaid
classDiagram
  class MainRepo{
    + .git/
    + worktrees/
    + objects/
  }
  class WorktreeMeta{
    + gitdir
    + index
    + locked
  }
  MainRepo "1" -- "N" WorktreeMeta : 各 worktree の<br>メタ情報
  WorktreeMeta <|-- WorktreeFolder
  class WorktreeFolder{
    + 作業ディレクトリ
    + .git (ファイル)<br>→ .git/worktrees/xxx
  }
```

### 4‑2. 共有／非共有ファイル

* **共有**: Git オブジェクト (`objects/`, `refs/` ほか)
* **個別**: `HEAD`, `index`, `config.worktree` など “作業ツリー固有” ファイル
* `config.worktree` (Git 2.26+) により sparse‑checkout やフック設定をツリー単位で分離可能

### 4‑3. GC と自動クリーンアップ

* 既定値 **`gc.worktreePruneExpire = 3.months`**
* 取り外し可能メディアに置く場合は `git worktree lock` または期間延長推奨

---

## 5. よくある落とし穴と対策

| 症状                          | 原因                   | 解決策                                               |
| --------------------------- | -------------------- | ------------------------------------------------- |
| 同じブランチを別ツリーにチェックアウト不可       | ブランチは同時に 1 ツリーのみ     | `--detach` でコミットハッシュ checkout ／一時ブランチ作成           |
| `worktree is not sparse` 警告 | sparse‑checkout 設定ずれ | `git sparse-checkout disable` → 再設定               |
| ワークツリーのフォルダを手動で移動           | パス不一致                | `git worktree repair`                             |
| 削除時に「untracked files あり」    | 作業ツリーが汚れている          | `git worktree remove --force` または `.gitignore` 更新 |

```mermaid
flowchart TD
  A["同じブランチを<br>別ツリーで使えない"] -->|解決策| B("detach でハッシュ checkout<br>or 一時ブランチ")
  C["worktree is not sparse<br>警告"] -->|解決策| D("sparse‑checkout disable<br>→再設定")
  E["フォルダを手動移動"] --> F("worktree repair")
  G["remove 時 untracked"] --> H("--force または ignore 追加")

  class A,C,E,G bad;
  class B,D,F,H fix;
```

---

## 6. チームで運用するためのベストプラクティス

```mermaid
timeline
  title 運用ルール導入ステップ
  section Week 1
    ディレクトリ命名決定 : 2025-06-15 : 1d
  section Week 2
    エイリアス設定共有 : 2d
    CI に prune 組込 : 3d
  section Week 3
    IDE 互換テスト : 2d
  section Week 4
    sparse‑checkout 運用開始 : 3d
```

1. **ディレクトリ構造統一**
   例：`../worktrees/{feature|release|hotfix}-<name>` で種別を先頭に
2. **定期的な `git worktree prune`**
   CI ジョブや pre‑push フックで自動実行
3. **エイリアス活用**

   ```ini
   [alias]
     wt = worktree
     wtl = worktree list
     wta = worktree add -b
   ```
4. **IDE / ツール互換性チェック**
   路径解決がリポジトリルート基準かを確認
5. **大規模リポでの sparse‑checkout 併用**
   ワークツリーごとに対象ディレクトリだけ展開し、ビルド時間を短縮

---

## 7. まとめ

* **`git worktree` は clone を増やさず“枝分かれした作業ツリー”を即席で作成**。
* `add / list / remove / prune / lock / move / repair` を押さえれば日常利用は OK。
* メタ情報は `.git/worktrees` に集約され、`git gc` と `worktree prune` が掃除役。
* **緊急 Hotfix・長期リリース保守・CI デバッグ・mono‑repo 部分 checkout** まで応用範囲広し。
* チームで**命名規則・自動 prune・IDE 連携** を合意し、並行開発をストレスなく回そう！

> これで **clone 地獄** から卒業。
> `git worktree` を武器に、複数ブランチを **並行・安全・高速** に扱う新しい開発スタイルを始めましょう。