你的 PR 已经有三个 approved review,CI 全部绿色,但 GitHub 的合并按钮显示灰色,悬停后提示「Required status checks must pass before merging」或「Merging is blocked」。又或者合并按钮是可点击的,但点击后立刻弹出「merge blocked by branch protection」。分支保护规则是团队安全防线,不能绕过,但它的配置错综复杂,很多时候卡住不是代码问题,而是规则配置与当前 PR 状态的细节错位。
常见原因
1. Required status checks 名称与 CI job 名称不匹配
最高命中率。在 Settings > Branches 里配置了必须通过的 status check 名称(如 ci/build),但 CI 实际上报的名称是 CI / build (ubuntu-latest) 或 build,名称不完全一致,Git 平台认为该 check 从未运行,永远无法满足。
怎么判断:在 PR 页面底部展开「Checks」列表,查看实际 check 的名称;再到 Settings > Branches 查看 Required checks 配置的名称,对比是否完全一致(区分大小写)。
2. Code owner review 未满足
仓库配置了 CODEOWNERS 文件,PR 涉及的文件有对应的 code owner,但该 owner 还未 review。即使其他人已经 approved,也不满足「Required review from code owners」规则。
怎么判断:PR 页面的 reviewers 区域若显示「Review required from code owners」,且对应 owner 未点 approve,就是这种情况。检查 .github/CODEOWNERS 或仓库根目录的 CODEOWNERS 文件。
3. 分支未与目标分支保持同步(需要 up-to-date)
「Require branches to be up to date before merging」规则要求 PR 分支包含目标分支的所有最新 commit。若 main 有新提交而 PR 分支没有 merge 或 rebase,合并被阻止。
怎么判断:PR 页面出现「This branch is out-of-date with the base branch」提示,需要点击「Update branch」或在本地 git merge main 后 push。
4. Required reviews 数量不足或有 change-requested review 未解决
设置要求最少 2 个 approvals,但 PR 只有 1 个。或者某个 reviewer 留了「Request changes」,即使后续代码已修复,该 reviewer 未重新提交 review,「change requested」状态仍然存在。
怎么判断:PR 页面 Reviewers 区域查看各 reviewer 的状态图标。橙色圆圈表示 requested changes,必须由该 reviewer 重新 approve 或管理员 dismiss。
5. PR 作者是分支 owner 但规则不允许自己 merge
「Restrict who can push/merge」规则设置了只有特定团队或角色可以合并。PR 作者不在该列表里,即使 review 全通过也无法点击 merge。
怎么判断:查看 Settings > Branches > Branch protection rules 里的「Restrict who can push to matching branches」配置,确认是否有此限制。
6. Signed commits 要求未满足
规则要求所有 commit 必须用 GPG 或 SSH 签名,但 PR 里有未签名的 commit(通常是通过 GitHub UI 编辑产生的,或者本地未配置 GPG)。
怎么判断:PR 的 commits 列表里,未签名的 commit 旁边没有绿色的「Verified」徽章。
最短修复路径
Step 1:查看 PR 底部的具体阻断原因
GitHub/GitLab 在合并按钮旁边会列出所有未满足的规则,展开后查看每条要求的当前状态。
Step 2:修复 status check 名称不匹配
# 在 .github/workflows/ci.yml 里确认 job 名称
# 确保 Settings > Branches 里的 Required checks 名称与此完全一致
# 修改工作流 job 名称示例:
# jobs:
# build: <- 这是 job ID
# name: CI / build <- 这是显示名称,required checks 应填这个
Step 3:更新分支使其与目标分支同步
git checkout feature/my-pr
git fetch origin
git merge origin/main
# 或者
git rebase origin/main
git push --force-with-lease origin feature/my-pr
Step 4:清除 change-requested review
联系留下 request changes 的 reviewer 重新查看并 approve,或者(若有管理员权限)在 PR 页面选择 dismiss 该 review 并说明原因。
Step 5:补齐 code owner review
检查 CODEOWNERS 文件找出对应文件的 owner:
cat .github/CODEOWNERS
# 或
cat CODEOWNERS
直接 @ 对应 owner 要求 review,或者申请管理员修改 CODEOWNERS 文件。
Step 6:为未签名 commit 补签名(若有 GPG 要求)
# 配置 GPG 签名
git config --global user.signingkey <your-gpg-key-id>
git config --global commit.gpgsign true
# 重签最近 N 个 commit
git rebase --exec 'git commit --amend --no-edit -S' HEAD~N
git push --force-with-lease
预防建议
- 新仓库配置分支保护规则后,先用测试 PR 走一遍完整流程,验证规则名称、reviewer 数量、check 名称全部正确。
- 在
CODEOWNERS文件旁边维护一份注释说明,标明哪些目录的 owner 是谁,方便 PR 作者提前知道需要找谁 review。 - 在 PR 模板(
.github/PULL_REQUEST_TEMPLATE.md)里加一个 checklist,提醒作者「已经 @ code owner review」、「分支已 rebase 到最新」。 - 使用 GitHub 的「Required status checks」时,先创建 CI workflow 并成功运行一次,确认 check 名称格式后再添加到保护规则。
- 若团队使用 GPG 签名,在 onboarding 文档里提供配置步骤,并在 CI 里加 pre-merge check 验证所有 commit 已签名。
- 定期审查分支保护规则,移除已离职人员作为唯一 code owner 的配置,避免 PR 永远无法合并。
常见问答 (FAQ)
Q: 管理员能绕过分支保护规则吗? A: 在 GitHub 上,仓库管理员默认不受分支保护规则约束,可以直接 merge。但可以在规则设置里勾选「Do not allow bypassing the above settings」,让管理员也受规则约束。GitLab 有单独的 Maintainer 角色设置。
Q: required status checks 设置了但 CI 还没跑,能手动触发满足吗?
A: 不能伪造 check 状态。需要触发 CI 重新运行:在 PR 页面点击「Re-run all jobs」,或者 push 一个空 commit:git commit --allow-empty -m "trigger ci" && git push。
Q: 两个 required reviewer 其中一个离职了,PR 永远合不了怎么办? A: 管理员可以 dismiss 该 reviewer 的 pending review request,然后分配新的 reviewer。或者更新分支保护规则,减少 required reviewers 数量,或更换为在职成员。
Q: GitLab 的 merge request 也有类似的保护机制吗? A: 有。GitLab 的对应功能叫 Protected Branches,配置在 Settings > Repository > Protected Branches。规则包括 allowed to merge/push 的角色、required approvals、code owners 等,诊断思路与 GitHub 相同。
相关阅读
- Force push 覆盖了队友的 commit
- Clone 之后 git hooks 不执行
- AI 把 secret 推到公开仓库了
- 凭证 helper 锁住,pull / push 全失败
- AI 帮你解决合并冲突
- Rebase 之后 commit 消失了
标签: #git #version-control #排查