Git如何限制分支被误删?有没有类似保护分支的机制?

文章导读
经常有同事问:Git 怎么防止分支被误删?有没有类似代码托管平台那种“保护分支”的机制?我一般会先反问一句:你用 Git 命令行,还是用 GitHub 这类平台?因为答案不一样。
📋 目录
  1. 平台保护分支是主流做法
  2. 配置时要把“删除”和“强制推送”一起管住
  3. 分支匹配范围用通配符时要先列清单
  4. 本地删除分支的坑:-D 和远端删除
  5. 误删分支之后,先查 reflog 再决定要不要恢复
A A

经常有同事问:Git 怎么防止分支被误删?有没有类似代码托管平台那种“保护分支”的机制?我一般会先反问一句:你用 Git 命令行,还是用 GitHub 这类平台?因为答案不一样。

平台保护分支是主流做法

Git本身并没有提供类似“分支保护”的原生能力,但常见的Git托管平台如GitHub、GitLab、Bitbucket都实现了保护分支(Protected Branch)功能。它的核心效果是:普通成员不能直接删除受保护分支,也不能强制推送到受保护分支;分支的删除和强制推送必须通过合并请求或额外授权完成。启用路径通常在仓库的Settings -> Branches中,针对指定分支或通配符添加规则。需要注意的是,这些能力是平台层实现的,而非Git命令的一部分,所以在本地用git push --delete时仍然会收到服务器的拒绝。

这个机制解决的是远端分支的“被删除”问题。本地分支想删随时能删,但推到远端时,只要目标分支受保护,服务器就会返回错误。所以你先要分清楚:你要防的是远端分支被删,还是本地分支被自己手滑删掉。大部分同事问的是前者。

配置时要把“删除”和“强制推送”一起管住

在 GitHub 上新建保护规则时,如果你只是勾选了“Require a pull request before merging”,并没有限制删除。真正的关键是下面这些选项:

Git如何限制分支被误删?有没有类似保护分支的机制?

以GitHub为例,在Settings的Branches页面新建规则时,最关键的是勾选“Require a pull request before merging”和“Require status checks to pass”这类选项,而防止误删则必须确认“Allow deletions”开关没有被开启。如果勾选了Allow deletions,那么即使分支受保护,有权力的协作者仍然可以直接删除分支。在GitLab中,对应的选项是“Allowed to force push”和“Allowed to delete”,需要将这两个权限设为禁止,才真正实现了分支不可被误删。一个常见坑是:管理员自己通常可以绕过规则,因此保护分支只对普通开发者和常规操作起作用,并非绝对的安全网。

配置完以后,我习惯用一个普通成员的账号去试删一次分支,确认会被拒绝。注意不要用管理员账号试,因为管理员经常能绕过规则,会得出“规则没生效”的错觉。

Git如何限制分支被误删?有没有类似保护分支的机制?

分支匹配范围用通配符时要先列清单

保护规则不是只能针对 main 或 master,也可以写通配符。但这里有个容易踩的坑:如果规则写成 *,把所有分支都保护起来,那么开发分支、个人分支也会被一并保护,临时分支删不掉,合并起来就很麻烦。我一般会先跑一下 git branch -a 把现有分支列出来,再决定是精确匹配几个长期分支,还是用 v/*、feature/* 这类前缀匹配。最好先确认一下通配符能覆盖到哪些分支,不要想当然。

本地删除分支的坑:-D 和远端删除

在本地执行git branch -d branch-name时,如果该分支还未合并到当前分支,Git会提示分支未合并并拒绝删除,并建议改用-D强制执行。误删最常见的原因是直接使用了-D,或者删除了尚未完全合并远端的分支。为了避免这类操作,可以在本地设置一个自定义别名,比如将delete-branch定义为先检查远端是否存在,再调用git branch -d,或者使用git branch -d命令时养成先检查合并状态的习惯。但本地逻辑无法限制对远端分支的删除,因为删除远端分支需要执行git push origin --delete branch-name,这项操作同样会直接触发平台上的保护分支规则。

如果你用的是 zsh 或 bash,可以给 git 配一个别名,类似:

Git如何限制分支被误删?有没有类似保护分支的机制?
git config --global alias.safe-delete '!f() { git ls-remote origin "$1" && echo "远端存在,请确认" || git branch -d "$1"; }; f'

这个写法有它的局限性,但还是能减少在本地直接 -D 的冲动。真正远端分支能不能删,最终还是要看平台规则。

误删分支之后,先查 reflog 再决定要不要恢复

如果保护规则没生效,或者压根儿没设保护,分支被删了也别立刻断言“完了”。Git 的 reflog 会记录分支曾经指向的提交,通常保存 90 天。可以先在误删分支的本地仓库执行 git reflog,找到删除前的 commit,再用 git branch branch-name <commit> 恢复。如果分支已经推送过远端,而删除者的本地仓库还有对应引用,同样能找回来。不过这取决于 reflog 是否过期,以及有没有做过 gc。保护分支只降低误删概率,不能当作备份。所以对特别重要的分支,我建议定期把远端分支 clone 到一块冷存储里,或者至少保留一个持续推送的备份仓库。