やりたかったこと(または「症状」)

複数のfeatureブランチを並行して作業するためにgit worktreeを使っていた。ある日、以前作業していたfeature-loginブランチのworktreeディレクトリが不要になったと判断し、git worktree removeではなく普通にrm -rfでディレクトリごと削除した。

後日、同じブランチで別の場所に作業ディレクトリを作り直そうとしたところ、git worktree addがエラーで失敗した。

git worktree add ../feature-login feature-login
fatal: 'feature-login' is already used by worktree at '/home/dev/project-feature-login'

すでにディレクトリはrm -rfで消しているのに、Gitはまだそのworktreeが存在するものとして扱っていた。パスを変えて実行しても同じエラーになった。

git worktree add ../feature-login-v2 feature-login
fatal: 'feature-login' is already used by worktree at '/home/dev/project-feature-login'

ブランチ名を変えずに別ディレクトリへworktreeを追加すること自体ができない状態だった。

環境

  • OS: Ubuntu 24.04.4 LTS
  • Git: 2.51.0
  • リポジトリ構成: メインの作業ディレクトリ1つ+featureブランチごとのworktreeを../配下に複数作成する運用
  • 削除したworktreeディレクトリ: /home/dev/project-feature-logingit worktree removeを使わずrm -rfで削除)

試したこと

まず、Gitが認識しているworktreeの一覧を確認した。

git worktree list
/home/dev/project                  a1b2c3d [main]
/home/dev/project-feature-login    e4f5g6h [feature-login]

実ディレクトリはすでに存在しないはずなのに、git worktree listには/home/dev/project-feature-loginが現役のworktreeとして表示されていた。試しにそのパスへ移動してみると案の定ディレクトリごと存在しなかった。

cd /home/dev/project-feature-login
bash: cd: /home/dev/project-feature-login: No such file or directory

次に、git branchで該当ブランチの状態を確認した。

git branch -v
* main            a1b2c3d Latest commit on main
  feature-login   e4f5g6h Add login form validation

ブランチ自体は残っており壊れてはいなかった。問題はブランチではなく、Gitの内部メタデータ側に「このブランチは/home/dev/project-feature-loginでチェックアウト中」という古い記録が残っていることだと分かった。

原因

git worktreeはメインリポジトリの.git/worktrees/配下に、各worktreeの管理情報(対応ディレクトリのパスや、どのブランチをチェックアウトしているか)を保持している。git worktree removeコマンドを使えば、この管理情報とディレクトリの両方が整合性を保ったまま削除される。

しかし今回のようにrm -rfでディレクトリだけを直接削除すると、.git/worktrees/側の管理情報は消えずに残ってしまう。Gitから見ると「feature-loginブランチは今も/home/dev/project-feature-loginというworktreeでチェックアウト中」という状態のままになるため、同じブランチを別の場所へworktree addしようとすると、二重チェックアウトを防ぐ安全機構が働いてis already used by worktreeエラーになる。これは壊れているのではなく、Gitが「削除されたことをまだ知らない」だけの状態だった。

解決方法

1. 現在のworktree一覧を確認する

git worktree list

存在しないパスが残っていないか確認する。

2. 存在しなくなったworktreeの管理情報を掃除する

git worktree pruneを実行すると、実ディレクトリが存在しないworktreeの管理情報を安全に削除できる。

git worktree prune -v
Removing worktrees/project-feature-login: gitdir file points to non-existent location

3. worktree一覧を再確認する

git worktree list
/home/dev/project    a1b2c3d [main]

feature-loginのworktreeエントリが消え、ブランチが「どこにもチェックアウトされていない」状態に戻った。

4. 改めてworktreeを追加する

git worktree add ../feature-login feature-login
Preparing worktree (checking out 'feature-login')
HEAD is now at e4f5g6h Add login form validation

エラーなくworktreeが作成できた。

動作確認

git worktree list
/home/dev/project                a1b2c3d [main]
/home/dev/project-feature-login  e4f5g6h [feature-login]

新しいディレクトリでfeature-loginブランチが正しくチェックアウトされていることを確認できた。

ハマったポイント

  • rm -rfでworktreeディレクトリを消しただけでは、Git側の管理情報(.git/worktrees/配下)は自動的にクリーンアップされない。必ずgit worktree removeを使うか、消した後にgit worktree pruneを実行する必要がある
  • エラーメッセージのis already used by worktreeだけを読むと、あたかも今もどこかで使用中であるかのように見えるが、実際にはディレクトリがすでに存在しない「幽霊worktree」であるケースが多い。慌てて--forceを付けて回避する前に、まずgit worktree listで実体の有無を確認するべきだった
  • git worktree add --forceでも同じブランチを別worktreeに強制的にチェックアウトできるが、同一ブランチを複数worktreeで同時に触ってしまうと、コミット漏れや意図しない上書きの原因になるため、根本原因(管理情報の残留)を解消する方が安全

よくある質問

Q: git worktree removeを使わずに消してしまった場合、他に影響はありますか? ディレクトリと管理情報が不整合になるだけで、コミット履歴やブランチ自体が壊れることはない。git worktree pruneで管理情報を整理すれば元通りに使える。

Q: git worktree pruneは他のworktreeにも影響しますか? 実体が存在するworktree(きちんとcdできるディレクトリ)には影響しない。あくまで実ディレクトリが見つからないエントリだけが対象になる。

Q: 今後同じ問題を避けるにはどうすればいいですか? worktreeを不要にする際は必ずgit worktree remove <path>を使う。手動でrm -rfした場合は、忘れずにgit worktree pruneをセットで実行する運用にしておくとよい。

関連記事