cleanup-branches
リモートが削除されたローカルブランチを削除できます(`[gone]`の上流シグナルが対象)。スカッシュマージ、リベースマージ、マージコミットのいずれのワークフローにも対応しています。
description の原文を見る
Remove local branches whose remote was deleted (the `[gone]` upstream signal). Works for squash-merge, rebase-merge, and merge-commit workflows alike.
SKILL.md 本文
/cleanup-branches、マージ済みブランチのクリーンアップ
リモート追跡参照が上流で削除されたローカルブランチを削除しています。これは、すべてのGitHubマージ方式を通じて確実に機能する唯一のクリーンアップヒューリスティックです。各ステップを順番に実行してください。実行する前に各コマンドを表示してください。
git branch --merged main ではなくこのヒューリスティックを使う理由
git branch --merged main は、チップコミットが main の祖先にあるブランチのみを認識します。スカッシュマージとリベースマージは、マージされたコンテンツの新しいコミットハッシュを作成するため、ソースブランチのチップは 決して main の祖先には含まれません。--merged ヒューリスティックはスカッシュマージされたすべてのブランチを無視してしまい、ユーザーはクリーンアップできないオーファンブランチを蓄積してしまいます。
確実なシグナルは git branch -vv の出力に表示される [gone] であり、これはローカルブランチのリモート追跡上流が削除されたときに表示されます(通常はGitHubの「マージ時にヘッドブランチを削除」設定によってPRがマージされたときに自動的に実行されます)。リポジトリが delete_branch_on_merge=true を持ち、ユーザーがチェック前に git fetch --prune を実行すれば、スカッシュ、リベース、マージコミットのいずれでも機能します。
リポジトリが delete_branch_on_merge を有効にしていない場合、マージ時に上流は決して削除されず、[gone] マーカーは表示されず、このスキルは正しく何もすることがないと報告します。ユーザーに設定を有効にするよう指示してください:
gh api -X PATCH repos/<owner>/<name> -f delete_branch_on_merge=true
ステップ 1: リモート追跡参照を更新
フェッチとプルーンを実行して、最後のフェッチ以降にオリジンで削除されたブランチがローカルで [gone] 上流として反映されるようにします:
git fetch --prune
ステップ 2: 削除された上流を持つブランチをリスト表示
実行します:
git branch -vv | awk '/: gone\]/ {print $1}'
これは1行に1つのブランチ名を出力し、各ブランチはリモート追跡参照が存在しなくなったローカルブランチです。これらは削除しても安全です(スカッシュ、リベース、またはマージコミットを使用してマージされ、マージ時にリモートブランチは自動削除されました)。
ステップ 3: リストをフィルタリング
ステップ 2 の出力から、以下のブランチは表示されたとしても 決して 削除してはいけません(通常は表示されないはずです。main と master は通常 gone 上流を追跡していないため、安全ネットとして扱います):
mainmaster
次にユーザーに尋ねます: 「このリストから保持したいブランチはありますか? カンマで区切って名前を入力するか、スキップするにはEnterキーを押してください。」
残りのブランチが削除の候補です。{branches_to_delete} として保存します。
ステップ 4: ユーザーに確認
{branches_to_delete} が空の場合:
- 「削除された上流ブランチが見つかりません。すべき処理はありません。」と出力します。
- 停止します。
削除するブランチがある場合、それらを表示します:
以下のブランチが削除されます(オリジン上の上流が [gone] です):
{各ブランチを別々の行にリストアップ}
尋ねます: 「これらのブランチを削除しますか? (yes/no)」
- no の場合: 「クリーンアップがキャンセルされました。ブランチは削除されませんでした。」と出力して停止します。
- yes の場合: 続行します。
ステップ 5: 各ブランチを削除
{branches_to_delete} の各ブランチに対して、実行します:
git update-ref -d refs/heads/{branch}
update-ref を使い、git branch -d や -D ではない理由:
git branch -d {branch}は「ブランチが完全にマージされていない」というエラーで拒否します。スカッシュマージとリベースマージの場合、git は標準的な意味でそれらをマージとして認識できないためです(上記の「このヒューリスティックを使う理由」を参照)。このスキルが対象とするケースでは毎回失敗します。git branch -D {branch}(強制)は機能しますが、ユーザーの破壊的なbashガードフック(~/.claude/hooks/guard-destructive-bash.ps1)は文脈に関係なく文字列パターンgit branch -Dをブロックします。git update-ref -d refs/heads/{branch}は参照を直接削除し、ポーセリンレベルのマージチェック(このケースでは正しい。gone-upstream がすでに検証した同等のマージシグナルであるため)を行わず、破壊的なbashガードの文字列一致からも逃れます。
削除がエラーで失敗した場合、それを報告し、リストの残りで続行します。1つの失敗でクリーンアップ全体を停止しないでください。
以下をカウント保持します:
- 正常に削除されたブランチ
- 削除に失敗したもの(理由付き)
ステップ 6: レポート
サマリーを出力します:
ブランチのクリーンアップが完了しました。
削除: {count} ブランチ
プルーン: {count} リモート追跡参照(開始時)
削除に失敗したブランチがある場合:
スキップ: {count} ブランチ(詳細は上記を参照)
正常に削除されたブランチ名と、理由付きでスキップされたブランチをリスト表示します。
エッジケース
[gone]上流を持ち、オリジンより先行するローカルコミット未コミット変更があるブランチ:update-ref -dは削除されます。ユーザーはマージされていない作業を失う可能性があります。対策: ステップ 4 の確認プロンプトが、ユーザーがリストを検査する機会です。git log {branch}を実行して main にないコミットを見つけた場合、スキルにそのブランチを保持するよう指示します。- まったく上流がないブランチ(プッシュされたことがない):
[gone]リストに表示されず、タッチされません。正しい動作です。プッシュされたことのないローカルブランチのクリーンアップは対象外です。 - デタッチされたHEAD: ステップ 2 の awk パターンは
* (HEAD detached at ...)行とマッチしません。正しい動作です。削除可能なブランチではありません。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- iam6ft7in
- ライセンス
- MIT
- 最終更新
- 2026/5/11
Source: https://github.com/iam6ft7in/cfg_dev_environment / ライセンス: MIT