3. 保护分支与合并权限设计
在大型团队中,分支协作的核心风险不是“没人写代码”,而是“谁都能往关键分支写”。保护分支(Protected Branch)与合并权限设计,本质上是在 GitLab 中为不同分支划定一条清晰的权限边界:哪些角色可以直接推送,哪些角色只能通过合并请求(Merge Request,MR)进入,合并前必须满足哪些审批条件。本节围绕保护分支、审批规则、代码所有者(Code Owners)和最小审批人数四个要素,说明如何把这条边界落到可执行的配置上。
一、保护分支:先定义“不可随意写入”的边界
保护分支解决的是写入权限问题。以常见的 main、release/* 为例,团队通常希望:主干分支不允许任何人直接 git push,只能通过 MR 合入;发布分支只允许发布负责人合并;普通开发分支则保持开放。在 GitLab 中,进入 Settings → Repository → Protected branches 即可配置,关键字段包括:
- Branch:分支名或通配符,如
main、release/*、hotfix/*。 - Allowed to merge:允许点击合并的角色,例如 Maintainer。
- Allowed to push and merge:允许直接推送并合并的角色,主干分支通常设为 No one。
- Allowed to force push:是否允许强制推送,主干分支必须关闭。
一个可直接参考的配置示例如下(角色按 GitLab 默认层级):
main Allowed to merge: Maintainer Push: No one Force push: 关闭
release/* Allowed to merge: Maintainer Push: No one Force push: 关闭
hotfix/* Allowed to merge: Maintainer Push: Maintainer Force push: 关闭
develop Allowed to merge: Developer Push: Developer Force push: 关闭
feature/* Allowed to merge: Developer Push: Developer Force push: 允许(仅个人分支)
这里要强调一个判断依据:“Allowed to push”设为 No one 并不等于没人能改主干,而是强制所有变更走 MR。这样代码审查、流水线校验和审批记录才有统一的入口。若某分支确实需要紧急直推,应单独建 hotfix/* 并限定到具体角色,而不是放开 main。
二、合并请求审批规则:把“能合并”变成“满足条件才能合并”
保护分支只控制“谁能合”,审批规则控制“满足什么条件才能合”。在 Settings → Merge requests 中,与权限边界最相关的选项有:
- Merge request approvals:启用审批,设置最小审批人数。
- Prevent approval by author / committers:禁止作者或提交者自审,避免“自己写自己批”。
- Reset approvals on push:新提交后重置已有审批,防止“批完再改”。
- Pipelines must succeed:流水线通过才允许合并。
- All threads must be resolved:所有讨论必须解决。
这些选项组合起来,才构成完整的合并门槛。例如主干分支可以设为:最小审批 2 人、禁止作者自审、推送后重置审批、流水线必须成功、讨论全部解决。此时即使某人是 Maintainer,也不能绕过审批直接合并——除非该分支的“Allowed to merge”被显式放开。
三、代码所有者:让“该谁审”由目录结构决定
最小审批人数只规定“几个人批”,但不规定“谁来批”。代码所有者通过仓库根目录的 CODEOWNERS 文件,把目录或文件映射到具体团队或个人,GitLab 会在 MR 中自动请求对应审批人。示例:
# CODEOWNERS
* @team-core
/src/payment/ @team-payment @li.ming
/src/auth/ @team-security
/infra/terraform/ @team-sre
/docs/ @tech-writers
配合保护分支中的 Code owner approval 选项,可以要求“涉及该路径的变更必须由对应 Code Owner 批准”。这样,支付模块的改动不会只由前端同学批准,安全相关目录也不会被无关人员放行。需要注意两点:一是 CODEOWNERS 的匹配遵循“最后匹配优先”,越具体的规则应写在越后面;二是 Code Owner 审批与最小审批人数是叠加关系,不是替代关系。
四、最小审批人数:按分支风险分级,而不是一刀切
最小审批人数应随分支风险递增。一个可落地的分级参考如下:
| 分支类型 | 最小审批人数 | 是否需 Code Owner | 典型场景 |
|---|---|---|---|
| feature/* | 1 | 否 | 日常功能开发 |
| develop | 1~2 | 关键目录需要 | 集成分支 |
| release/* | 2 | 是 | 版本发布 |
| main | 2~3 | 是 | 生产主干 |
人数不是越多越好。审批人过多会导致 MR 长时间挂起,反而促使团队寻找绕过手段。更合理的做法是:主干 2 人且其中至少 1 人为 Code Owner,发布分支 2 人,普通功能分支 1 人。若某类变更风险极高(如数据库迁移、支付逻辑),可对特定路径单独提高要求。
五、把四要素串成一条权限边界
下面这张图展示了从开发者提交到合并进入主干的完整权限判定链:保护分支决定“能不能推”,审批规则与最小人数决定“够不够批”,Code Owner 决定“该谁批”,流水线与讨论状态决定“是否放行”。
从图中可以看到,权限边界不是单一开关,而是四层叠加:保护分支拦截直推,MR 作为唯一入口,审批规则与最小人数控制批准数量,Code Owner 控制批准质量,流水线与讨论状态作为最终放行条件。任何一层缺失,都会留下绕过路径。
六、落地时的常见判断与调整
配置完成后,建议用一次真实 MR 做验证:让一名 Developer 尝试直接推送 main,应被拒绝;再提交一个 MR,观察是否自动请求 Code Owner、是否要求 2 人审批、推送新提交后审批是否重置。若发现 Maintainer 仍能绕过审批直接合并,检查该分支的“Allowed to push and merge”是否被误设为 Maintainer。若 Code Owner 未被自动请求,检查 CODEOWNERS 路径是否匹配、是否启用了 Code owner approval。
CODEOWNERS 纳入主干保护范围,修改它本身也需要审批,否则有人可以通过改规则来绕过审批。总结来说,保护分支、审批规则、代码所有者和最小审批人数共同构成 GitLab 大型团队的分支写入与合并权限边界。设计时应按分支风险分级,主干从严、功能分支从简,并保证所有变更都经过 MR 这一统一入口,让权限边界既安全又可执行。