用 Rulesets 保护 GitHub 的 main 分支
摘要
- 本文写给一个仓库的
main加上规则:禁止直接推送、禁止 force push、合并前必须通过指定的 Actions 检查。页面按 Creating rulesets for a repository 的当前流程。 - 分支上的 Pull Request 怎么开,见 Git安装和常用命令(最新) 第 27 节和 给别人的 GitHub 仓库提 Pull Request。提交签名见 用 SSH 密钥签名 Git 提交。Actions 里检查项的名字见 GitHub Actions Workflow 详细指南。
- Available rules for rulesets。
规则拦的是推送
有写权限的人可以直接 git push origin main,Pull Request 和 Actions 都不会跑。git push --force 还会改掉 main 上已经存在的提交,别人基于旧历史做出的分支会对不上。规则写在 GitHub 上,由服务器拒绝这两种推送。功能分支不受影响,仍可 git push -u origin feature/xxx。
本文只写单个仓库的分支规则。组织里一批仓库共用的规则要 GitHub Team 或 GitHub Enterprise。按文件路径、大小拦截推送的是 push ruleset,只对私有或 internal 仓库生效,这里不写。
创建
打开仓库的 Settings。左侧在 Code, planning, and automation 下进入 Rulesets,再点一次 Rulesets。然后 New ruleset → New branch ruleset。
-
Ruleset name:例如
protect-main。 -
Enforcement status:选 Active。停在 Disabled 时,推送不会被拦。选 Evaluate 时推送仍然成功,页面上可以查看这次会违反哪些规则,用来先试再开。
-
Target branches:Add target → Include default branch。仓库的默认分支是
main时,这条就作用在main上。 -
Bypass list 先留空。把 Repository admin 加成 Always allow 之后,管理员的
git push origin main仍然成功,看起来像规则没生效。 -
Branch rules 勾选下面三项。Restrict deletions 和 Block force pushes 页面上经常已经勾着,确认它们是开的。
| 规则 | 作用 |
|---|---|
| Restrict deletions | 不能删除 main |
| Block force pushes | git push --force 到 main 会被拒绝 |
| Require a pull request before merging | 变更要先有一个 Pull Request。这里不要求必须有人批准 |
勾了 Require a pull request before merging 之后,还可以填批准人数。填 1 时,至少一名有写权限的人批准后才能合并。自己一个人的仓库会因此合并不了自己的 PR,个人仓库可以保持不填,只留下「必须走 PR」这条记录。
点 Create。状态是 Active 时立即生效。
加上 Actions 检查
在同一条规则里勾 Require status checks to pass before merging。输入框里填检查的名字,再点添加。只打字、不添加,保存后这条检查不存在。
名字必须和 Pull Request 的 Checks 列表里那一项一致,例如 workflow 里 jobs 下的键是 build 时,这里通常就填 build。多一个空格会配不上,合并按钮会一直等一个不会出现的检查。
Require branches to be up to date before merging 打开时,功能分支要先接上最新的 main,检查才会被认作通过。这项在启用状态检查后默认是开的。检查名字还没添加时,这一项不会单独生效。
要求每个提交都已签名时,再勾 Require signed commits。签名方法见 用 SSH 密钥签名 Git 提交。分支上若已有未签名的提交,需要改写那些提交再推;Block force pushes 同时开着时,没有 Bypass 权限就推不上去。个人仓库先不要两样一起开。
确认已经生效
规则保存后,向 main 推一次。服务器拒绝时,输出里有 Repository rule violations,并写明违反的规则,例如必须通过 Pull Request。
1 | git push origin main |
这条失败,只说明 main 被拦住了。功能分支应仍能推上:
1 | git push -u origin feature/xxx |
功能分支也失败时,看 Target branches 是不是写成了全部分支。管理员推 main 却成功时,打开这条规则的 Bypass list。
停用或删除
还在 Rulesets 列表里点开 protect-main。把 Enforcement status 改成 Disabled 后保存,规则留着但不再拦截。不需要这条规则时,在页面上 Delete。删的是 GitHub 上的规则,本机仓库不用改。