git worktree 入門:stashをやめて作業を並行させる
開発環境
- pnpm
- git
前提
開発中に「レビュー依頼が来たので一旦別ブランチを見たい」「差し込みの緊急対応が入った」というシーン、よくあると思います。
これまでは都度 git stash してブランチを切り替えていましたが、作業途中のファイルが多いと地味に面倒で、切り替え後に「あれ、さっき何をしていたんだっけ」と作業の流れが切れてしまうこともありました。
git worktree を使うと、作業ディレクトリ自体を分けられるので、今の作業を崩さずに別ブランチを扱えます。この記事では素の git コマンドだけで完結する運用手順をまとめます(エディタや利用ツールを問わず使えます)。
本題
やりたいこと
- 開発中にレビュー依頼が発生し、一旦別ブランチにチェックアウトしたいが作業中で面倒
- 開発中に別の作業が差し込まれ、一旦保留になってしまう
→ 作業ディレクトリを分ければ、今の作業を崩さず(stash不要)に別ブランチを扱えます。
手順1: worktreeの置き場所を決める
.gitignore に .worktrees/ を登録しておき、この配下にworktreeを作るようにしています。こうすればリポジトリを汚さずに済みます。
# .gitignore
.worktrees/手順2: worktreeを作る
レビュー依頼のように既存ブランチを見る場合と、差し込み対応のように新規ブランチで作業する場合とで、コマンドが少し変わります。
# 既存ブランチ(レビュー依頼など)
git worktree add .worktrees/pr-review origin/feature/reviewed-branch
# 新規ブランチ(差し込み作業など)
git worktree add .worktrees/urgent-task -b fix/urgent-task-namegit worktree add <path> <branch> が基本形です。-b を付けると新規ブランチを同時に作成できます。
手順3: 依存関係と環境変数を整える
新しいworktreeは元のリポジトリと別ディレクトリ扱いなので、node_modules や .env は自動では付いてきません。
cd .worktrees/urgent-task
pnpm install
cp ../../.env ..env はプロジェクトによって参照元が変わるので、上記はあくまで一例です。
⚠️ エディタは開き直す
VSCodeで作業している場合、同じウィンドウのまま cd .worktrees/urgent-task しても差分表示は元のworktreeのまま切り替わりません。VSCodeを一旦閉じて、.worktrees/urgent-task を新規ウィンドウとして開き直す必要があります。
code .worktrees/urgent-taskここを忘れると「worktreeを分けたはずなのに差分がおかしい」と混乱するので注意です。
手順4: 作業が終わったらworktreeを片付ける
git worktree list # 一覧確認
git worktree remove .worktrees/pr-review⚠️ 注意点
- ブランチは1つのworktreeでしか使えません(同じブランチを2箇所で同時チェックアウトは不可)
- .next のようなビルドキャッシュも各worktreeで独立するため、初回ビルドはやや遅くなります
シェル関数にして手順をまとめる
手順1〜3を毎回手打ちするのは面倒なので、シェル関数にしておくと楽になります。
wt() {
git worktree add ".worktrees/$1" -b "$1" && cd ".worktrees/$1" && pnpm install
}wt fix/urgent-task-name と打つだけで、ブランチ作成・worktree作成・ディレクトリ移動・installまで一気に終わります。
pnpmはnode_modulesを共有できる
worktreeを増やすたびに node_modules が重複して肥大化するのでは、と気になったので調べてみました。
pnpmはcontent-addressableなグローバルストアを使っていて、node_modules の中身は実体ファイルへのハードリンク/シンボリックリンクで構成されています。
- 共有される:パッケージの実体データ(ストアに一度キャッシュされていれば重複コピーされません)
- 共有されない:node_modules のディレクトリ構造自体(worktreeごとに独立するので、pnpm install の実行自体は毎回必要です)
.npmrc / pnpm-workspace.yaml に store-dir のカスタム設定がなければ、pnpmデフォルトのグローバルストアが使われます(プロジェクト内に .pnpm-store ディレクトリがなければ、この状態です)。
つまり、2つ目以降のworktreeでの pnpm install は、既にストアにあるバージョンならネットワークダウンロード不要でリンク作業のみになるため高速です。worktreeを気軽に作って捨てる運用と相性が良いことがわかりました。
参考: Claude Codeを使っているなら .worktreeinclude もある
余談ですが、Claude Codeを使っている場合は .worktreeinclude という機能(docs)で、上記の手順3(.env のコピー)を自動化できます。
# .worktreeinclude
.env
.env.localプロジェクトルートに置いておくと、Claude Codeが --worktree フラグやEnterWorktreeツール経由でworktreeを作成する際に、gitignore対象のファイルを自動でコピーしてくれます。ただし素の git worktree add を自分で打った場合は読まれないので、その場合は今まで通り手動コピーが必要です。
Claude Codeを使っていない場合は無視して問題ありません。
さいごに
git worktree は名前だけ知っていて手を出せていなかった機能でしたが、実際に運用フローを組んでみると、stashによる作業中断のストレスがほぼなくなりました。
素のgitコマンドだけで完結するので、エディタやツールを問わず使えるのも良いところです。シェル関数化とpnpmのストア共有による高速installを組み合わせれば、worktreeを「気軽に作って気軽に捨てる」運用ができます。
レビュー依頼や差し込み対応が頻繁に発生するプロジェクトでは、ぜひ試してみてください。