过期分支不清理会成为团队协作的定时炸弹,必须通过精准时间判断、规避误删场景、结合pre-receive钩子与CI校验等综合策略安全清理。

过期分支不清理,迟早会变成团队协作的定时炸弹——不是“要不要清”,而是“怎么清才不丢数据、不误删、不卡流程”。
feature 分支存活超过 7 天就该预警
Git 本身不记录分支创建时间,但 commit 时间戳可推断活跃度。实际项目中,feature 分支超过 7 天未合并,冲突概率陡增,CI 流水线也容易因 base 提交陈旧而误报失败。
- 用
git log -1 --format=%cd --date=iso feature/login查分支最新提交时间,比git branch --sort=-committerdate更准(后者按本地 reflog 排序,可能被 reset 干扰) - 不要只看“是否已合并”:有些分支虽已 merge,但没删,仍会出现在
git branch列表里,干扰 PR 过滤和权限策略 - 开发周期超限的分支,优先检查是否被拆分遗漏、需求变更未同步,或 CI 检查长期失败未处理——清理前先确认“人因问题”
自动清理脚本必须避开三类误删场景
直接 git branch -d 批量删 feature 分支,常导致 hotfix 丢失、release 分支被连带清除、或刚合入但尚未打 tag 的分支被删掉。
检查并更新通过 GitHub git clone 安装的 OpenClaw skills,适用于用户提到“更新skill”“检查 skill 是否有新版本”“GitHub 安装的 skill 是否有更新”“帮我检查本地 skills 是否落后”“更新 git clone 装的 skill”“拉取...
- 保留最近 N 个 hotfix 分支:
git branch --format="%(refname:short) %(committerdate:short)" --sort=-committerdate | grep "^hotfix/" | tail -n +4 | cut -d' ' -f1 | xargs git branch -d - 跳过含未 push 提交的分支:
git branch --format="%(refname:short) %(upstream:remotename)" | awk '$2 != \"origin\" {print $1}'过滤掉本地未推送到远端的分支 - 排除已 merge 但尚未打 tag 的 release 分支:
git branch --merged main | grep "^release/" | while read b; do git tag --points-at $(git rev-parse $b) | grep -q "v[0-9]" || echo "skip $b"; done
pre-receive 钩子拦截超期分支推送
仅靠事后清理不够,应在分支创建阶段就设防。GitHub/GitLab 不支持服务端 pre-commit,但 pre-receive 可在远端拦截非法分支命名或超期分支更新。
- 在 Git 服务器
.git/hooks/pre-receive中加入判断逻辑,例如禁止向feature/分支推送距今超 14 天的 commit:git log $1..$2 --format=%ct | awk '{if (systime() - $1 > 1209600) exit 1}' - 注意:钩子不能依赖
git describe或外部命令超时,否则阻塞推送;所有时间计算必须用 Unix timestamp,避免时区歧义 - 该机制对 fork 后的 PR 不生效(因为 PR 是通过 refs/pull/xxx/head 推送),需配合 CI 在 PR 创建时校验 base 分支 age
CI/CD 合并后自动删除需绑定两个前提条件
很多团队开了 “delete head branch after merge” 选项,结果发现 develop 上少了一次 hotfix 合并,或者 release 分支删早了导致 tag 锚点失效。
- 必须确保
git merge --no-ff已执行且成功返回:某些 CI 配置在 merge 失败后仍触发删除动作 - 必须验证 tag 是否已打在目标分支(如 main)上:
git tag --points-at $(git rev-parse main) | grep "^v[0-9]",否则说明 release/* 尚未完成发布闭环 - 删除操作应走异步 job,而非 post-merge shell 脚本——避免因网络抖动或权限问题导致删除失败却无日志可查
真正难的不是写个脚本删分支,而是定义清楚“这个分支还能不能动”:它是否还在 QA 环境跑回归?有没有灰度开关依赖它的 commit hash?有没有运维手册引用了它的分支名?这些信息不会出现在 git branch 输出里,得靠人和流程兜底。

















