核心是精准控制外包权限边界:锁死主干分支,仅开放匹配前缀的专用分支推送权,强制MR流程与自动化审核,并通过团队级管理和自动归档实现交接退出闭环。

外包团队接入 Git,核心不是“能不能给权限”,而是“给什么权限、在哪给、怎么收”——不设边界等于放任风险。
为什么直接给 Developer 权限很危险
很多团队图省事,把外包人员加进项目直接给 Developer 角色,结果很快出现:误推代码到 main 分支、删掉 CI 配置文件、提交含敏感信息的调试日志。这不是外包不守规矩,而是权限粒度没对齐实际协作场景。
-
Developer允许向所有非保护分支推送,但外包通常只参与特定功能模块,不需要写入整个仓库 - Git 平台(如 GitLab/GitCode/Gitea)的默认角色是按“人”分配的,而外包协作本质是按“任务”隔离的
- 一旦外包成员离职或更换,手动清理权限容易遗漏,尤其当他们还混在多个项目里时
用 Protected Branches + 自定义角色切出最小可行权限
真正的边界控制不在“加谁”,而在“拦什么”。关键动作是:先锁死主干分支,再为外包开一条受控通道。
- 在项目设置中启用
Protected Branches,将main、release/*等分支设为“仅Maintainer可合并”,并勾选“不允许强制推送” - 创建专用分支规则,比如允许
feature/outsourcing-*或hotfix/external-前缀分支由外包推送,其他分支一律拒绝 - 如果平台支持(如 GitLab 16.0+),可新建自定义角色,只赋予
push到匹配分支 +create merge request权限,不给delete branch或edit project settings - 外包提交必须走
Merge Request流程,且 MR 模板强制填写“关联需求编号”“测试验证说明”,避免黑盒交付
外包代码怎么审?别只靠人工点“Approve”
单纯卡权限只能防误操作,防不住逻辑错误或隐蔽风险。审核必须嵌入流程,而不是挂在最后一步。
- 在 MR 触发时自动运行
git diff --name-only origin/main,过滤出外包修改的文件路径,若包含.env、config/database.yml、Dockerfile等高危路径,直接阻断 CI 并报错 - 要求外包 PR 描述中必须带
Fixes #ISSUE_ID或Refs #TASK_ID,否则 MR 无法通过状态检查(可用 GitLab 的require_issue_reference策略) - 设置
Require approval from specific users,指定内部技术负责人必须审批,且禁止自己审批自己的 MR(GitLab 支持prevent_self_approval) - 对
feature/outsourcing-类分支启用Require pipelines to pass,CI 脚本里加入grep -r "console.log" . --include="*.js"等轻量级扫描,拦截调试残留
交接和退出机制比接入更关键
外包人员换人、项目阶段结束、合同终止——这些时刻最容易暴露权限管理漏洞。自动化兜底比人工提醒可靠得多。
- 所有外包账号统一加进一个
external-contractors团队(GitCode/Gitea 支持 Team 层级权限),而非直接加项目。权限变更只需改 Team 设置,不用逐个点项目 - 设置账号有效期:GitCode 支持 SCIM 同步 Azure AD 的
accountExpires字段;Gitea 可配合 LDAP 的shadowExpire属性自动禁用 - 每次外包交付后,执行脚本自动归档其分支:
git push origin :feature/outsourcing-payment-v2(注意冒号前有空格),避免分支堆积干扰后续开发 - 季度审计时重点查
git log --since="3 months ago" --author="outsourcing@.*" --oneline,确认无绕过 MR 的直推记录
外包协作最难的不是技术配置,而是让内部团队接受“所有外部输入都默认不可信”。权限边界不是用来防外包的,是用来防自己疏忽的。


















