git worktreeで並行作業をちょっと便利にする

## はじめに
皆さんは`git worktree`というgitコマンドを利用したことがあるでしょうか。
私は恥ずかしながら、最近までこのコマンドの存在さえ知りませんでした。

このコマンドに出会ったのは、巷で話題のClaude Codeについて調べていた時のことです。
Anthropic社が公開している[Claude Code: Best practices for agentic coding](https://www.anthropic.com/engineering/claude-code-best-practices#:~:text=c.-,Use%20git%20worktrees,-This%20approach%20shines)というドキュメント内に、`Use git worktrees`という章がありました。

調べていると、2つ以上並行して`Claude Code`を利用する以外にも便利に利用できそうであったため、備忘録を兼ねて記事にしたいと思います

## TL;DR
- `git worktree`というコマンドを利用することで、独立した作業ディレクトリを作成することができる。
	  - その作業ディレクトリは、cloneしたリポジトリとコミットログなどを共有している
- 複数ブランチをまたいだ開発時に、作業内容を`stash`したり一旦`commit`したりすることなく、別ブランチの作業ディレクトリを作成できるため、非常に便利

## git worktreeコマンドとは
`git worktree`は、同一リポジトリに対して複数の作業ディレクトリを作成できるGitコマンドです。
通常は、cloneしたディレクトリ上でブランチを適宜切り替えながら作業すると思いますが、`git worktree`を利用することで複数の作業ディレクトリを作成できます。
ワークツリーの主な操作として、この記事では以下のコマンドを解説します。
- git worktree add
- git worktree list
- git worktree remove
- git worktree prune
- git worktree lock
- git worktree unlock

### git worktree add
ワークツリー(作業ディレクトリ)を新たに作成するコマンドです。
以下のコマンドを実行すると、`<ディレクトリの作成先のパス>`に`<対象ブランチ名>`がチェックアウトされた状態の独立した作業ディレクトリを作成できます。
```bash
$ git worktree add <ディレクトリの作成先のパス> <対象のブランチ名>
Preparing worktree (checking out '<対象のブランチ名>')
HEAD is now at <コミットID> <コミットメッセージ>
```

また、制約として、既に別のワークツリーでチェックアウトしているブランチを指定するとエラーが発生します。
複数のワークツリーから一つのブランチに対して作業を行うことはできません。

また、新しいブランチを作成して、そのブランチのワークツリーを作るには`-b`オプションを利用できます
```bash
$ git worktree add <ディレクトリのパス> -b <対象のブランチ名>
Preparing worktree (checking out '<対象のブランチ名>')
HEAD is now at <コミットID> <コミットメッセージ>
```

## git worktree list
現在作成されているワークツリーの一覧が表示できます
```bash
$ git worktree list
<ディレクトリパス> <HEADのコミットID> [<ブランチ名>]
<ディレクトリパス> <HEADのコミットID> [<ブランチ名>]
<ディレクトリパス> <HEADのコミットID> [<ブランチ名>]
……
```

## git worktree remove
指定したワークツリーを削除するコマンドです。
ワークツリーの参照だけでなく、ディレクトリの内容も削除されます。
```bash
$ git worktree remove <ディレクトリのパス>
```

## git worktree prune
不要なワークツリーの参照が削除されます。
例えば、作成したワークツリーのディレクトリが`rm`コマンドで削除された場合、実際にはワークツリーは存在しませんが、参照が残ってしまいます(git worktree listでも表示されます)。
`git worktree prune`を実行することで、実際には存在しないワークツリーの参照を削除することができます。
```bash
$ git worktree prune
```

## git worktree lock
ワークツリーを`remove`や`prune`による削除から保護することできます。
例えば、クラウドストレージ上のワークツリーが`prune`コマンドで誤って削除されるような悲劇を防ぐことができます。
```bash
$ git worktree lock <ディレクトリパス>

$ git worktree remove <ディレクトリパス>
fatal: cannot remove a locked working tree;
use 'remove -f -f' to override or unlock first
```

## git worktree unlock
ワークツリーのロックを解除できます。
```bash
$ git worktree unlock <ディレクトリパス>
```

## 活用方法
ワークツリーの作成が有効なのは、複数のブランチで並行して作業を進めたい場合です。

例えば、自分が`feture-A`ブランチで作業中に、`feature-B`ブランチのレビューを依頼されたとします。
ワークツリーを新規に作成しない場合には、以下の手順を踏むことになります。
1. `feature-A`ブランチの変更をstash、もしくはcommitする
2. `feature-B`ブランチにチェックアウト
3. `feature-B`ブランチのレビューを実施
4. `feature-A`ブランチにチェックアウトして、作業再開

これが、ワークツリーを作成するととてもシンプルになり、かつ`feature-A`ブランチの変更を退避する必要がありません。
1. `feature-B`ブランチのワークツリーを作成
2. `feature-B`ブランチのレビューを実施
3. 不要になった`feature-B`のワークツリーは削除

もちろん、Claude Codeを利用するような、2つ以上の独立した修正を並行して進めるような場合にも効果を発揮します。

## リポジトリを複数cloneする運用との違い
実は、以前からレビュー時の一時的な修正内容のstashを煩わしく感じていました。
その解決手段として自分が行っていたのは、レビュー専用に同じRepositoryをもう一つクローンしておくという解決策でした。

この方法に比べて、ワークツリーの作成にはいくつかの利点があると感じています。
- .gitファイルが共有されることで、コミット履歴をfetchする必要なく共有できます
- `git worktree list`コマンドで、ワークツリーのパスを一元管理できます。cloneを複数行った場合には、自分でパスを覚えておく必要があります。 
- repositoryのcloneはそのサイズによってはかなりの時間がかかります。ワークツリーの作成は、cloneに比べて短時間で終了します。

## まとめ
`git worktree`コマンドを活用することで、並行作業をシンプルな方法で進めることができます。
特に作業途中でレビューや緊急対応を行う必要があるときに、stashによる修正内容の対比を行う必要がないので便利です。
また、リポジトリを複数クローンしておく方法と比べても、その準備と管理のしやすさ両方に利点がありそうです。

Claude Codeでの同時並行な作業だけでなく、レビュー時などに積極的に利用できる機能だと感じました！