git-branch-cleanup について
保護対象ブランチにマージ済みのローカルGitブランチを特定し、対象を削除するスキルです。保護対象と現在のブランチを残し、候補ごとの根拠を示してから確認を求めます。
主な機能
- 01ローカルの保護対象へのマージ済みブランチを特定
- 02保護対象と現在のブランチを保持
- 03候補ごとのマージ先を表示
- 04削除前に確認を要求
- 05安全な `git branch -d` のみ使用
活用シーン
- 01マージ済み作業ブランチの整理
- 02削除前の候補確認
- 03保護対象やチェックアウト中のブランチの保持
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ chann/ skills --skill git-branch-cleanupインストール後、Claude Code で/git-branch-cleanupを入力して読み込まれたか確認します。
同梱ファイルagents/openai.yamlevals/evals.json
詳細
Git ブランチのクリーンアップ
概要
保護対象ブランチのいずれかに完全にマージ済みで、安全に削除できるローカルブランチを見つけて削除します。保護対象の名前(main、master、dev、develop、development、stg、stage、staging、root)と現在のブランチは、常に保持されます。
開始時にアナウンスします:「git-branch-cleanup スキルを使用して、保護対象ブランチにすでにマージ済みのローカルブランチを削除します。」
保護対象ブランチ
以下のブランチ名は、マージ状況にかかわらず削除しません。
main、master、dev、develop、development、stg、stage、staging、root
現在のブランチも削除しません。
ワークフロー
ステップ 1:一覧を確認する
git fetch --prune 2>/dev/null || true # informational; keeps refs honest, don't error if offline
current=$(git branch --show-current)
[ -n "$current" ] || { echo "Detached HEAD; checkout a branch first." >&2; exit 1; }
protected=(main master dev develop development stg stage staging root)
# All local branch names
all=$(git for-each-ref --format='%(refname:short)' refs/heads/)
ステップ 2:保護対象ブランチのうち、ローカルに実在するものを確認する
ローカルに存在する保護対象ブランチのみ、マージ先として使用できます。
anchors=()
for p in "${protected[@]}"; do
git rev-parse --verify "$p" >/dev/null 2>&1 && anchors+=("$p")
done
if [ "${#anchors[@]}" -eq 0 ]; then
echo "No protected branches (main/master/dev/develop/development/stg/stage/staging/root) found locally; nothing to anchor against." >&2
exit 1
fi
ステップ 3:候補を特定する
以下の条件をすべて満たすブランチが候補です。
- 保護対象リストに含まれていない
- 現在のブランチではない
- 少なくとも 1 つのアンカーからその先端に到達できる(つまり、完全にマージ済みである)
candidates=()
for b in $all; do
# skip protected
case " ${protected[*]} " in *" $b "*) continue ;; esac
# skip current
[ "$b" = "$current" ] && continue
# merged into any anchor?
for a in "${anchors[@]}"; do
if git merge-base --is-ancestor "$b" "$a"; then
candidates+=("$b|$a") # remember which anchor proved it
break
fi
done
done
各エントリには branch|anchor を保存し、各候補をなぜ削除するのか計画で示せるようにします。
ステップ 4:計画を提示して確認する
Plan: delete N merged local branches
feature/oauth-login (merged into main)
bugfix/null-response (merged into main)
chore/update-deps (merged into develop)
Kept (protected or current):
main, develop, stage ← protected
feature/in-progress ← current branch
Proceed? (y/N)
candidates が空の場合 →「クリーンアップ対象はありません。マージ済みの保護対象外ブランチは見つかりませんでした。」とユーザーに伝えて終了します。
明示的な確認を待ちます。既定値はいいえです。
ステップ 5:-d で安全に削除する
for entry in "${candidates[@]}"; do
branch="${entry%%|*}"
if git branch -d "$branch"; then
echo "✓ deleted $branch"
else
echo "✗ refused $branch — left intact (run \`git branch -d $branch\` manually if you're sure)"
fi
done
-D(強制)は絶対に使用しないでください。マージ済みだと判断した候補に対して -d が拒否した場合は、何かがおかしいため、報告してスキップします。強制削除に切り替えてはいけません。
ステップ 6:概要
git branch # show what remains
echo "Done. Deleted M of N candidates."
スキップした候補がある場合は、そのブランチを列挙し、-d に拒否されたことを説明します(アンカーから実際には到達できないコミットがブランチに含まれている可能性があります。例:--no-commit による cherry-pick や、書き換えられた履歴)。
実例
User: 머지된 브랜치 다 정리해줘
current = main
anchors found locally: main, develop
Local branches:
main ← protected, kept
develop ← protected, kept
feature/oauth-login → ancestor of main? yes → candidate
bugfix/null-response → ancestor of main? yes → candidate
feature/wip-experiment → ancestor of any anchor? no → kept (not yet merged)
hotfix/typo → ancestor of develop? yes → candidate
Plan: delete 3 (feature/oauth-login, bugfix/null-response, hotfix/typo)
User confirms.
→ git branch -d feature/oauth-login ✓
→ git branch -d bugfix/null-response ✓
→ git branch -d hotfix/typo ✓
→ Show remaining branches: main, develop, feature/wip-experiment.
注意すべき点
絶対に行わないこと:
git branch -D(強制削除)を使うこと。このスキルで許可されているのは-d(安全な削除)のみです- 保護対象リスト(
main、master、dev、develop、development、stg、stage、staging、root)内のブランチを削除すること - 現在のブランチを削除すること
- リモートブランチを削除すること(
git push origin --delete ...)。このスキルの対象はローカルのみです - 確認プロンプトを省略すること
- マージされていない古いブランチを候補として扱うこと。候補となるのは完全にマージ済みのブランチのみです
必ず行うこと:
- 各候補の根拠となるアンカーを示したうえで計画を提示する(ユーザーが確認できるようにするため)
- 保持したブランチとその理由を示す
- マージ状況の確認には
git merge-base --is-ancestorを使う(HEAD とのマージ状況しか確認しないgit branch --mergedは使わない) - 確認の既定値を「いいえ」にする
よくある間違い
--is-ancestor の代わりに git branch --merged を使う
- 問題:
--mergedが確認するのは現在のブランチに対するマージ状況のみで、すべての保護対象アンカーに対してではありません - 対処: アンカーごとに
git merge-base --is-ancestorを実行します。そうすれば、mainにはマージされていなくてもdevelopにマージ済みのブランチを検出できます
-d が拒否したときに強制削除する
- 問題: 安全確認がリスクを正しく検出しているにもかかわらず、
-Dを使ってしまうことです - 対処: そのブランチをスキップして報告し、ユーザーの判断に委ねます
現在のブランチを候補に含める
- 問題: 現在チェックアウトしているブランチは削除できず、Git にも拒否されます
- 対処: 候補リストを作成する前に、現在のブランチを除外します
連携
併用するスキル:
git-merge-to-main/git-merge-to-dev— これらのスキルはマージ直後に単一のソースブランチを削除します。このスキルは、すでにマージ済みのブランチをすべてクリーンアップします
呼び出し元: ユーザーが手動で呼び出した場合のみです。他のスキルのワークフロー中に自動実行してはいけません。