最近、1つのリポジトリで複数のタスクを同時に進める機会が増えてきました。
- A機能の実装中に、Bの軽微な修正依頼が入る
- レビュー待ちの間に別ブランチの作業を進める
- AIにコード生成を頼みながら試行錯誤する
これまでは `git stash` を使って切り替えていましたが、徐々に限界を感じるようになりました。
そこで使い始めたのが `git worktree` です。
今回は、`git stash` 運用から `git worktree` に移行した理由と、実際の使い方、そしてローカル開発を快適にする工夫についてまとめます。
git worktreeとは?
`git worktree` は、1つのリポジトリから複数の作業ディレクトリを作成できる機能です。
通常はこうなります。
project/
└ mainブランチ
しかし、`git worktree` を使うと
project/ (main)
project-featureA/ (featureA)
project-bugfix/ (bugfix)
のように、同じリポジトリの別ブランチを別フォルダで同時に開けるようになります。
git stashとの違い
`git stash` は、
「今の変更を一時退避して、ブランチを切り替える」ための機能です。
一方 `git worktree` は、
「ブランチごとに物理的に作業ディレクトリを分ける」機能です。
stash運用の課題
- stash → checkout → pop の往復が地味にストレス
- pop忘れで変更が迷子になる
- コンフリクトが発生しやすい
- 複数作業を同時に“開いておけない”
git worktreeの良いところ
- それぞれ独立したフォルダで作業できる
- `git stash` 不要
- 物理的に分かれているので思考も整理しやすい
- VSCodeを複数ウィンドウで開ける
個人的には「脳のメモリを節約できる」のが一番大きいです。
なぜ git worktree を使うようになったのか
きっかけは単純で、`git stash` 運用に限界を感じたことでした。
もともとは、
- 作業中に別タスクが割り込む
- レビュー待ちの間に別ブランチを触る
- 一時的に変更を退避する
といった用途で `git stash` を使っていました。
しかし、AI駆動開発を取り入れてから状況が変わります。
AIと開発するようになって変わったこと
AIと一緒に開発するようになってから、次のような動きが日常になりました。
- とりあえず実装してみる
- 別案をすぐ試す
- 大胆にリファクタリングする
- ダメなら戻す
つまり、「実験前提」の開発サイクルが一気に増えました。
その結果、
- 途中状態を保持したまま別作業に移りたい
- 実験ブランチを複数同時に開いておきたい
- 思考を完全に分離したい
というニーズが強くなりました。
作業ツリーが1つでは足りなくなった
`git stash` は一時退避には便利ですが、
複数の作業状態を「同時に開いたまま」並列で扱う用途には向いていません。
AI駆動開発では、
“今の状態を閉じずに別の実験を始める” という動きが頻繁に発生します。
その結果、
「作業ツリーが1つ」という前提そのものがボトルネックになりました。
そこで導入したのが `git worktree` です。
環境を物理的に分けることで、
実験・修正・レビュー対応を同時に走らせられるようになりました。
きっかけは stash の煩雑さ。
本質は、AIと一緒に開発する今、作業ツリーが1つでは足りなくなったこと。
これが `git worktree` を使い始めた一番の理由です。
git worktreeの基本的な使い方
基本的なコマンドはそこまで多くありません。
よく使うものだけ押さえれば、すぐに運用できます。
1. 既存ブランチを追加する
git worktree add ../project-featureA featureA
これで、
- ../project-featureA というディレクトリが作成され
- featureA ブランチがその中にチェックアウトされます
ブランチごとに物理的な作業フォルダができる、というのがポイントです。
2. 新規ブランチを作りながら追加する
まだブランチがない場合は、-b を使います。
git worktree add -b featureB ../project-featureB
新規ブランチ作成と同時にworktreeを追加できます。
AI実験用のブランチを切るときは、この形をよく使っています。
3. worktreeの一覧を確認する
git worktree list
どのディレクトリがどのブランチなのか確認できます。
4. 不要になったら削除する
git worktree remove ../project-featureA
これは作業ディレクトリのみ削除します。
ブランチはそのまま残ります。
5. 不要なworktree情報を整理する
手動でディレクトリを削除した場合など、
Git内部に古いworktree情報が残ることがあります。
その場合は、以下のコマンドで整理できます。
git worktree prune
これにより、存在しないディレクトリへの参照がクリーンアップされます。
並列開発を長く続けるとworktreeが増えていくため、
定期的に実行すると安心です。
以上が、基本的な使い方です。
やっていることは、実は単純で、ブランチごとにフォルダを分けているだけです。
ですが、この「物理的に分かれている」ことが、
AI駆動開発や並列作業において想像以上に効いてきます。
ここまで読むと分かる通り、コマンド自体はシンプルです。
ただ、並列開発を日常的にやるようになると、
- ブランチ名を考える
- worktreeを追加する
- cdする
- エディタを開く
という一連の流れを毎回やることになります。
正直、少しだけ面倒です。
そこで、シェルでまとめました。
シェルコマンドでローカル開発を楽にする
例えば、こんな関数を .zshrc に追加しています。(※一部簡略化)
wt () {
local branch="$1"
if [ -z "$branch" ]; then
echo "Usage: wt "
return 1
fi
local worktree_path="../$branch"
git fetch
# ローカルブランチが存在する場合
if git show-ref --verify --quiet "refs/heads/$branch"; then
git worktree add "$worktree_path" "$branch"
# リモートブランチが存在する場合
elif git show-ref --verify --quiet "refs/remotes/origin/$branch"; then
git worktree add -b "$branch" "$worktree_path" "origin/$branch"
# どちらも存在しない場合はデフォルトブランチから作成
else
git worktree add -b "$branch" "$worktree_path" origin/master
fi
code "$worktree_path" -n
}
実運用では、もう少しだけ工夫しています。
例えば:
- 特定のプレフィックスをworktree用のディレクトリ名に変換
- / を含むブランチ名を安全なディレクトリ名に変換
- 既にworktreeが存在する場合は再作成せずそのまま開く
- 必ず最新状態を取得してから判定する
といった処理を入れています。
さらに、エディタを開いたあとに使うローカル開発用シェルも用意しています。
- 依存パッケージのインストール
- ローカル用hostsの設定
- 開発サーバー起動
並列開発では、「ディレクトリを切ったらすぐ動かせる」状態にしておくことが重要です。
これにより、この2コマンドだけでローカルでの開発環境が整います。
wt feature-ai-test(ブランチ名)
wt-setup
まとめ
`git worktree` を導入してから、並列開発がぐっと自然になりました。
もちろんデメリットもあります。ディレクトリが増える分、ディスク容量はその分使用しますし、node_modules などの依存パッケージは共有されないため、worktreeごとにインストールが必要です。ただ、それも「環境が独立している」ことの裏返しだと考えています。
また、いくつか知っておきたい制約もあります。
- 同じブランチを複数のworktreeに同時に追加することはできない
- 手動でディレクトリを削除した場合は
git worktree pruneで整理が必要になることがある
ただし、これらを理解して運用すれば大きな問題にはなりません。
`git stash` でやりくりするのではなく、環境そのものを分ける。
さらにシェルで自動化しておけば、並列開発は特別なものではなくなります。
AI駆動開発が当たり前になりつつある今、作業ツリーをひとつに縛られないという選択肢は、思っている以上に開発体験を変えてくれるかもしれません。
並列作業やAI実験が増えている方には、特におすすめです。
よかったら一度試してみてください。