セキュリティ対応で複数のfeatureブランチを並行して進める必要が出てきました。最初は git stash してブランチを切り替えて、を繰り返していましたが、3ブランチとなるとかなり大変です。そこで使い始めたのが git worktree。
同じリポジトリを複数のディレクトリに展開できる機能で、.git を共有したまま作業ディレクトリだけ増やせます。リポジトリをまるごとクローンするより軽く、設定やリモートURLのコピーも不要。
今回の構成
feature/security-base という共通のベースブランチから、CSRF対策・XSS対策・セッションタイムアウトの3つを切る構成。
共通の親フォルダ/
├── project-main/ ← メインの作業ディレクトリ(別ブランチのままでOK)
├── csrf-fix/ ← feature/csrf-fix
├── xss-fix/ ← feature/xss-fix
└── session-timeout/ ← feature/session-timeout
project-main はいじらなくて大丈夫です。今作業中のブランチのままキープしつつ、worktreeだけ並べられます。
worktreeを作る
project-main のディレクトリから実行します。
git worktree add ../csrf-fix -b feature/csrf-fix origin/feature/security-base
git worktree add ../xss-fix -b feature/xss-fix origin/feature/security-base
git worktree add ../session-timeout -b feature/session-timeout origin/feature/security-base
-b feature/csrf-fix でブランチを新規作成しつつ、origin/feature/security-base を起点にしています。実行すると ../csrf-fix ディレクトリが生成され、すぐ cd して作業できる状態。あとはターミナルを3枚開いてそれぞれに入るだけです。
終わったら削除する
pushまで終わったらworktreeを片付けます。
git worktree remove ../csrf-fix
git worktree remove ../xss-fix
git worktree remove ../session-timeout
ここで詰まったのが、コミットしていない変更が残っていたときのエラーでした。
error: '../csrf-fix' contains modified local files
--force をつければ強制削除できます。ただし未コミットの変更は消えるので、削除前に git status での確認は必須。
git worktree remove --force ../csrf-fix
forceで消してしまっても、コミット済みのものは .git に残っているのでプッシュは可能です。
# project-main から
git push origin feature/csrf-fix
状態確認
git worktree list
ディレクトリが増えてくると「どれがどのブランチだっけ」となりがちです。パスとブランチ名をまとめて確認できるコマンドです。