GitHubでPRをマージしてリモートブランチを消しても、手元のローカルブランチって地味に残り続けますよね。
git fetch -p を実行すればリモート追跡ブランチは更新されますが、手元のローカルブランチ自体は自動では削除されず溜まっていきます。
git branch -vv を実行したとき、ブランチ名の横に gone と表示されるものがあります。これは「追跡先のリモートブランチが既に削除されている」ことを示すサインであり、クリーンアップの対象です。
実際の表示は以下のような形式になります。
feature-x 1234abc [origin/feature-x: gone] コミットメッセージ
* main 5678def [origin/main] コミットメッセージ
この記事では、この「リモートで消えたローカルブランチ」を安全に一括削除するコマンドと、それをエイリアス化して効率化する方法をまとめました。
リモートで消えたブランチを一括削除するコマンド
gone になった不要なローカルブランチを削除するには、以下の3ステップを実行します。
リモートブランチの最新状況を取得します。
git fetch -p
削除対象のブランチ名を一覧で確認します。
git branch -vv | sed 's/^[ *]*//' | grep ': gone]' | awk '{print $1}'
上記の一覧に問題がないことを確認したら、一括削除を実行します。
git branch -vv | sed 's/^[ *]*//' | grep ': gone]' | awk '{print $1}' | xargs git branch -d
コマンドの仕組みと注意点:
-
sed 's/^[ *]*//': 先頭の*とスペースを除去し、awkでのカラムずれを防ぎます。省略すると、チェックアウト中のブランチがgoneのときにawkが*を拾ってしまいます。 -
grep ': gone]':[origin/xxx: gone]の形式にマッチする文字列で、消失したリモートを追跡していたブランチだけを抽出します。 -
awk '{print $1}': 1列目のブランチ名だけを取り出します。 -
xargs git branch -d: 対象ブランチをまとめて削除します。-dなので未マージのブランチは安全にブロックされます。
エイリアス登録して 1 コマンドにする(git gone)
上記のコマンドを毎回手入力して実行するのは面倒なので、エイリアスに登録して git gone だけで呼び出せるようにします。ターミナルで次のコマンドを実行します。
git config --global alias.gone '!git branch -vv | sed "s/^[ *]*//" | grep ": gone]" | awk "{print \$1}" | xargs git branch -d'
※ macOS標準の zsh ターミナルから設定する場合、先頭の !(シェル実行フラグ)が zsh の履歴展開機能とバッティングしないよう、シングルクォート ' で囲んで実行してください。
これで今後は git gone と入力するだけで、不要になったローカルブランチを一括で安全に削除できます。実際にリモートでブランチを削除したのち git fetch -p && git gone を実行し、git branch -vv から該当ブランチが消えることを確認してみてください。
注意点
安全に運用するためのポイントです。
-
一括削除には
git branch -D(大文字D)を使わない
リモート側でPRがマージされて削除されたと思っても、ローカルに未プッシュのコミットが残っている場合があります。安全のため、一括削除には未マージを検知してブロックできる-d(小文字)を使い、Squash/Rebaseマージなどで-dにブロックされたブランチだけ、内容を確認したうえで個別に-Dで削除するようにしてください。 -
fetch.pruneを常時有効化しておく
毎回-pをつけなくてもリモート追跡ブランチが自動で整理されるよう、以下の設定を行っておくことを推奨します。git config --global fetch.prune true -
現在チェックアウト中のブランチが
goneになっていても、そのブランチ自体は削除されません
Gitはチェックアウト中のブランチを削除できない仕様のためエラーを出して失敗し、そのまま残ります。他のブランチに切り替えてからgit goneを再実行してください。
以上です!