mcpField
G
git-branch-cleanup

git-branch-cleanup

github.com/chann开发050 次安装2 天前更新
代码仓库

关于 git-branch-cleanup

用于查找已合并到受保护分支的本地 Git 分支,并清理符合条件的分支。它会保留受保护分支和当前分支,展示候选分支的合并依据,并在安全删除前要求确认。

主要功能

  1. 01查找已合并到本地保护分支的分支
  2. 02保留受保护分支和当前分支
  3. 03显示每个候选分支的合并依据
  4. 04删除前要求确认
  5. 05仅使用安全的 `git branch -d`

适用场景

  1. 01清理已合并工作的本地分支
  2. 02删除前检查清理候选项
  3. 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. 不在受保护列表中
  2. 不是当前分支
  3. 其提交顶端可从至少一个锚点到达(即已完全合并到该锚点)
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 验证合并状态(而不是使用 git branch --merged,后者只会检查相对于 HEAD 的状态)
  • 将确认的默认选项设为“否”

常见错误

使用 git branch --merged 而不是 --is-ancestor

  • 问题:--merged 只检查相对于当前分支的状态,不会检查所有受保护锚点
  • **解决方法:**遍历锚点并使用 git merge-base --is-ancestor,这样即使某个分支已合并到 develop(但未合并到 main),也能检测到

在 -d 拒绝删除时强制删除

  • **问题:**安全检查正确提示风险时,却转而使用 -D
  • **解决方法:**跳过该分支并报告;由用户决定

将当前分支列为候选分支

  • **问题:**无法删除当前所在的分支;Git 无论如何都会拒绝
  • **解决方法:**在生成候选列表前过滤掉当前分支

集成

搭配使用:

  • git-merge-to-main / git-merge-to-dev——这些技能会在合并后立即删除单个源分支;此技能则会清理所有已合并的分支

**调用方式:**仅由用户手动调用。绝不要在其他技能的工作流中自动运行。

评论

支持 Markdown