Monorepo 项目 Git 权限管控:详细操作步骤指南
基于 sichuanji-cc 项目(前面文章提及到的)的 Monorepo 架构(apps 应用层+packages 共享层)与团队协作痛点(如开发者误改跨模块代码、共享层变更无审核),本文通过 8个核心步骤,实现 Git 权限的精细化管控,确保“谁负责、谁操作,不越权、不误改”,同时兼容项目已有的 npm workspaces + Turbo 技术栈。
一、前置准备:明确目标与工具
在开始操作前,需对齐权限管控目标、确认角色分工与工具版本,避免后续配置混乱。
1.1 权限管控核心目标
- 限制 Web Dev 仅能操作
apps/web及依赖的共享目录(如packages/ui/shared),无法修改apps/admin或packages/database; - 确保 共享层(如
packages/auth/database)变更必须经过多角色审核,避免单一开发者修改导致全局故障; - 禁止 普通开发者直接推送
main/develop等核心分支,所有变更通过 MR 合并并触发审核; - 实现 跨目录修改自动拦截(如 Web Dev 误改
apps/admin时,CI 直接阻断)。
1.2 工具与环境准备
| 工具/平台 | 版本要求 | 核心作用 |
|---|---|---|
| GitLab | ≥15.0(或 GitHub ≥2.0) | 代码托管+分支保护+CODEOWNERS 支持 |
| Git | ≥2.30.0 | 本地分支管理与提交 |
| GitLab CI/CD | 与 GitLab 版本同步 | 权限拦截脚本执行 |
| 企业 IM(如飞书) | 任意 | 权限变更通知与审计结果同步 |
1.3 角色与账号映射表
提前在 GitLab 中创建项目角色并绑定开发者账号,后续权限配置将基于此表:
| 角色名称 | GitLab 账号示例 | 负责目录 | 核心操作权限 |
|---|---|---|---|
| 架构师 | @architect-li | 全目录(审核用) | 合并 main 分支、修改权限规则 |
| Web 开发负责人 | @web-lead-zhang | apps/web | 审核 Web 分支 MR、合并 release/web |
| Web 开发者 | @web-dev-wang | apps/web | 创建 feature/web-* 分支、提交 MR |
| Admin 开发负责人 | @admin-lead-liu | apps/admin | 审核 Admin 分支 MR、合并 release/admin |
| Admin 开发者 | @admin-dev-chen | apps/admin | 创建 feature/admin-* 分支、提交 MR |
| 核心服务开发 | @core-dev-zhao | packages/shared/auth/database | 创建 feature/core-* 分支、维护共享层 |
| UI 开发 | @ui-dev-xu | packages/ui | 创建 feature/ui-* 分支、维护组件库 |
| 工具链开发 | @devops-dev-song | packages/dev-tools | 维护 CI 脚本、开发工具配置 |
| 测试 | @tester-ma | 全目录(验证用) | 触发预发布部署、验证权限生效 |
二、步骤1:GitLab 仓库基础配置
先完成仓库初始化与角色添加,为后续权限配置打基础。
2.1 仓库创建(若未创建)
- 操作路径:GitLab 首页 → New project → Import project → 选择“Existing repository”
- 具体配置:
- 仓库名称:
sichuanji-cc - 可见性:私有(Private)(避免外部访问)
- 导入 URL:若从旧仓库迁移,填写旧仓库 Git 地址;若新建,直接初始化空仓库
- 仓库名称:
- 验证:访问
https://gitlab.com/[你的组名]/sichuanji-cc,确认仓库正常显示。
2.2 团队角色添加(核心操作)
将准备好的角色账号添加到仓库,并分配基础权限(避免过度授权):
- 操作路径:GitLab 仓库 → Settings → Members → Invite members
- 批量添加配置(按角色分组):
| 角色名称 | 输入账号 | 权限级别 | 有效期 |
|---|---|---|---|
| 架构师 | @architect-li | Maintainer(维护者) | 永久 |
| Web 开发负责人 | @web-lead-zhang | Maintainer | 永久 |
| Admin 开发负责人 | @admin-lead-liu | Maintainer | 永久 |
| 核心服务开发 | @core-dev-zhao | Maintainer | 永久 |
| Web 开发者 | @web-dev-wang | Developer(开发者) | 永久 |
| Admin 开发者 | @admin-dev-chen | Developer | 永久 |
| UI 开发 | @ui-dev-xu | Developer | 永久 |
| 工具链开发 | @devops-dev-song | Developer | 永久 |
| 测试 | @tester-ma | Reporter(报告者) | 永久 |
- 权限说明:
Maintainer:可配置分支保护、合并 MR(仅给负责人,避免普通开发者越权);Developer:可创建分支、提交代码、发起 MR(无权限修改权限规则);Reporter:可查看代码、触发 CI,但无法提交代码(适合测试角色)。
- 验证:用
@web-dev-wang(Web 开发者)账号登录 GitLab,确认能看到sichuanji-cc仓库,但无法进入「Settings」页面(无权限修改配置)。
三、步骤2:核心分支保护规则实操
针对 sichuanji-cc 项目的分支体系(main/develop/release/feature),逐一配置保护规则,实现“分支-角色”绑定。
2.1 主分支(main)保护:生产环境绝对安全
main 分支对应生产代码,需最严格的权限控制:
- 操作路径:GitLab 仓库 → Settings → Repository → Branch protection rules → Add rule
- 具体配置:
- Branch name pattern(分支匹配模式):填写
main(精确匹配主分支); - Protect matching branches(启用保护):勾选;
- Allowed to push(允许推送):选择“None”(禁止任何人直接推送,必须通过 MR);
- Allowed to merge(允许合并):仅选择“@architect-li”(仅架构师可合并到生产);
- Required approvals(必填审核数):设置为“2”(需2人审核通过,如架构师+对应模块负责人);
- Require approval from code owners(强制代码所有者审核):勾选(关联后续 CODEOWNERS 规则);
- Do not allow bypassing the above settings(禁止绕过规则):勾选(防止管理员强制推送)。
- Branch name pattern(分支匹配模式):填写
- 验证:
- 用
@web-dev-wang(Web 开发者)账号,本地执行git push origin main; - 预期结果:Git 报错
remote: You are not allowed to push code to protected branches on this project.(无权限推送)。
- 用
2.2 开发主分支(develop)保护:整合开发成果
develop 是开发环境基准分支,允许合并但禁止直接推送:
- 操作路径:同上,新增分支保护规则;
- 具体配置:
- Branch name pattern:填写
develop; - Allowed to push:选择“None”;
- Allowed to merge:选择所有角色(
@web-lead-zhang/@admin-lead-liu/@core-dev-zhao等 Maintainer 角色); - Required approvals:设置为“1”(需1名对应模块负责人审核);
- Require approval from code owners:勾选。
- Branch name pattern:填写
- 验证:
- 用
@web-dev-wang账号发起feature/web-test合并到develop的 MR; - 预期结果:MR 自动要求
@web-lead-zhang(Web 负责人)审核,审核通过后才能合并。
- 用
2.3 预发布分支(release/web/release/admin)保护:按应用隔离
release 分支对应预发布环境,仅允许对应应用的开发/测试操作:
(1)release/web 分支配置
- 操作路径:新增分支保护规则;
- 具体配置:
- Branch name pattern:填写
release/web; - Allowed to push:选择“@web-lead-zhang”(Web 负责人)+“@tester-ma”(测试);
- Allowed to merge:选择“@web-lead-zhang”+“@architect-li”(架构师);
- Required approvals:设置为“1”(测试审核预发布结果)。
- Branch name pattern:填写
(2)release/admin 分支配置
-
Branch name pattern:填写
release/admin; -
Allowed to push:选择“@admin-lead-liu”(Admin 负责人)+“@tester-ma”;
-
Allowed to merge:选择“@admin-lead-liu”+“@architect-li”;
-
Required approvals:设置为“1”。
-
验证:
- 用
@admin-dev-chen(Admin 开发者)账号,尝试推送代码到release/web; - 预期结果:Git 报错
remote: You are not allowed to push code to protected branches matching 'release/web' on this project.(无权限)。
- 用
2.4 功能分支(feature/*)保护:按角色隔离
通过“分支匹配模式”批量管控 feature 分支,确保 Web Dev 仅能操作 feature/web-*:
-
操作路径:新增分支保护规则;
-
具体配置:
- Branch name pattern:填写
feature/web-*(匹配所有 Web 功能分支); - Allowed to push:仅选择“@web-dev-wang”/“@web-lead-zhang”(Web 角色);
- Allowed to merge:仅选择“@web-lead-zhang”;
- Required approvals:设置为“1”(Web 负责人审核)。
- Branch name pattern:填写
-
同理配置
feature/admin-*分支:- Branch name pattern:
feature/admin-*; - Allowed to push:仅“@admin-dev-chen”/“@admin-lead-liu”;
- Allowed to merge:仅“@admin-lead-liu”。
- Branch name pattern:
-
验证:
- 用
@web-dev-wang账号创建feature/admin-test分支并推送; - 预期结果:Git 报错
remote: You are not allowed to push code to protected branches matching 'feature/admin-*' on this project.(无权限创建 Admin 功能分支)。
- 用
四、步骤3:CODEOWNERS 配置:目录级审核绑定
通过 CODEOWNERS 文件,实现“修改特定目录必须经对应角色审核”,解决“跨目录修改无拦截”问题。
3.1 创建 CODEOWNERS 文件
- 本地操作:在
sichuanji-cc仓库根目录,创建.gitlab/CODEOWNERS文件(GitLab 专用路径;若用 GitHub,路径为.github/CODEOWNERS); - 文件内容(贴合项目目录结构):
# ================= 应用层目录 =================
# apps/web:仅 Web 负责人审核
/apps/web/ @web-lead-zhang @web-reviewer
# apps/admin:仅 Admin 负责人审核
/apps/admin/ @admin-lead-liu @admin-reviewer
# ================= 共享层目录 =================
# packages/ui:UI 负责人+两端应用负责人审核(确保跨应用适配)
/packages/ui/ @ui-dev-xu @web-lead-zhang @admin-lead-liu
# packages/shared:核心开发+两端负责人审核(全局工具函数,影响所有应用)
/packages/shared/ @core-dev-zhao @web-lead-zhang @admin-lead-liu
# packages/auth:核心开发+架构师+运维审核(高风险,涉及安全)
/packages/auth/ @core-dev-zhao @architect-li @devops-dev-song
# packages/database:核心开发+架构师+运维审核(高风险,涉及数据)
/packages/database/ @core-dev-zhao @architect-li @devops-dev-song
# packages/dev-tools:仅工具链开发审核(低风险,不影响生产)
/packages/dev-tools/ @devops-dev-song
# ================= 根目录配置 =================
# CI 脚本:架构师+工具链开发审核(影响所有构建流程)
/.gitlab-ci.yml @architect-li @devops-dev-song
# 项目文档:架构师审核
/README.md @architect-li
3.2 提交 CODEOWNERS 文件
- 本地命令:
git add .gitlab/CODEOWNERS
git commit -m "feat: add CODEOWNERS for directory permission"
git push origin develop # 推送到开发主分支
- 验证:访问 GitLab 仓库 → Repository → Files → .gitlab → CODEOWNERS,确认文件正常显示。
3.3 验证 CODEOWNERS 生效
- 测试场景:用
@web-dev-wang账号修改apps/web/src/views/Home/Banner.vue,并提交 MR 到develop; - 预期结果:
- MR 页面自动显示“Required approvals from code owners”(需代码所有者审核);
- 审核人列表自动添加
@web-lead-zhang(CODEOWNERS 中配置的apps/web所有者); - 若未通过
@web-lead-zhang审核,MR 无法合并。
五、步骤4:CI/CD 权限拦截:技术阻断跨目录修改
通过 GitLab CI 脚本,在代码提交时自动检查“修改的目录是否在角色授权范围内”,实现“技术拦截”(即使权限配置遗漏,也能阻断)。
4.1 编写 CI 拦截脚本
在项目根目录创建 .gitlab-ci.yml 文件,添加“目录校验”阶段(validate-directory),优先于构建/测试阶段执行:
# .gitlab-ci.yml
# 定义流水线阶段(目录校验优先)
stages:
- validate-directory # 目录权限校验
- build # 构建(项目原有阶段,保留)
- test # 测试(项目原有阶段,保留)
- deploy # 部署(项目原有阶段,保留)
# ================= 目录权限校验任务 =================
validate-directory:
stage: validate-directory
image: alpine:latest # 轻量镜像,加速执行
only:
- merge_requests # 仅在 MR 时触发(避免正常开发阻塞)
script:
# 1. 安装 Git(alpine 镜像默认无 Git,需安装)
apk add --no-cache git
# 2. 获取 MR 变更的所有文件路径(对比目标分支与当前分支)
# CI_MERGE_REQUEST_TARGET_BRANCH_SHA:目标分支(如 develop)的 commit ID
# CI_COMMIT_SHA:当前分支(如 feature/web-test)的 commit ID
changed_files=$(git diff --name-only $CI_MERGE_REQUEST_TARGET_BRANCH_SHA $CI_COMMIT_SHA)
echo "=== 本次 MR 修改的文件 ==="
echo "$changed_files"
if [ -z "$changed_files" ]; then
echo "ERROR:未检测到修改文件,终止校验"
exit 1
fi
# 3. 定义「分支类型→允许修改的目录」映射(贴合项目角色与目录)
declare -A branch_dir_map
# Web 功能分支:仅允许修改 apps/web + 依赖的共享层
branch_dir_map["feature/web-*"]="^apps/web/|^packages/ui/|^packages/shared/|^packages/auth/"
# Admin 功能分支:仅允许修改 apps/admin + 依赖的共享层
branch_dir_map["feature/admin-*"]="^apps/admin/|^packages/ui/|^packages/shared/|^packages/auth/|^packages/database/"
# 核心共享层分支:仅允许修改 packages/shared/auth/database
branch_dir_map["feature/core-*"]="^packages/shared/|^packages/auth/|^packages/database/"
# UI 分支:仅允许修改 packages/ui
branch_dir_map["feature/ui-*"]="^packages/ui/"
# Web 预发布分支:仅允许修改 apps/web
branch_dir_map["release/web"]="^apps/web/"
# Admin 预发布分支:仅允许修改 apps/admin
branch_dir_map["release/admin"]="^apps/admin/"
# 4. 匹配当前分支对应的允许目录规则
current_branch=$CI_COMMIT_BRANCH
allowed_dirs=""
for pattern in "${!branch_dir_map[@]}"; do
if [[ $current_branch == $pattern ]]; then
allowed_dirs=${branch_dir_map[$pattern]}
break
fi
done
# 5. 检查是否匹配到规则(未匹配则需人工审核)
if [ -z "$allowed_dirs" ]; then
echo "WARNING:当前分支 $current_branch 无预设目录规则,需人工审核修改范围!"
exit 0 # 不阻断,但提示人工检查
fi
echo "=== 当前分支 $current_branch 允许修改的目录规则 ==="
echo "$allowed_dirs"
# 6. 校验每个修改的文件是否在允许范围内
for file in $changed_files; do
if ! echo "$file" | grep -E "$allowed_dirs"; then
echo "ERROR:文件 $file 不在授权范围内!"
echo "允许的目录规则:$allowed_dirs"
exit 1 # 阻断 CI 流程,禁止合并
fi
done
echo "=== 所有修改文件均在授权范围内,目录校验通过! ==="
# ================= 保留项目原有构建/测试/部署阶段 =================
# (以下为项目原有配置,无需修改,确保权限校验不影响原有流程)
build:
stage: build
image: node:18-alpine
script:
- npm install
- npm run build # 基于 npm workspaces + Turbo 的构建命令
test:
stage: test
image: node:18-alpine
script:
- npm run test
deploy:
stage: deploy
image: node:18-alpine
only:
- main # 仅生产分支触发部署
script:
- npm run deploy
4.2 提交 CI 脚本并验证
- 本地提交:
git add .gitlab-ci.yml
git commit -m "feat: add directory validation in CI"
git push origin develop
- 测试跨目录修改拦截:
- 用
@web-dev-wang账号创建feature/web-test-ci分支; - 修改
apps/admin/src/components/Button.vue(跨目录修改,Web Dev 无权限); - 提交 MR 到
develop,触发 CI 流水线; - 预期结果:
validate-directory阶段失败,日志显示ERROR:文件 apps/admin/src/components/Button.vue 不在授权范围内!,MR 无法合并。
- 用
六、步骤5:权限测试与验收
针对所有角色与分支,进行全场景测试,确保权限配置无遗漏。
5.1 测试用例设计(核心场景)
| 测试场景 | 操作角色 | 预期结果 |
|---|---|---|
普通开发者推 main 分支 | @web-dev-wang | 报错,无权限 |
Web Dev 创建 feature/admin-* 分支 | @web-dev-wang | 报错,无权限 |
Admin Dev 修改 packages/auth | @admin-dev-chen | MR 要求 @core-dev-zhao 审核,无审核无法合并 |
Web Dev 误改 apps/admin | @web-dev-wang | CI 校验失败,MR 阻断 |
架构师合并 release/web 到 main | @architect-li | 成功合并,无报错 |
5.2 验收标准
- 所有测试用例通过率 100%;
- 每个角色仅能操作职责范围内的分支与目录;
- 跨目录修改、越权分支操作均被阻断(要么 Git 报错,要么 CI 失败,要么 MR 无法审核)。
七、步骤6:定期权限审计操作
为避免“角色离职后权限未回收”“权限配置过时”等问题,需定期审计。
7.1 审计工具:GitLab API
通过 GitLab API 导出当前权限配置,无需手动检查:
- 获取分支保护规则:
# 替换 [PRIVATE_TOKEN](GitLab 个人访问令牌,需有 api 权限)、[PROJECT_ID](仓库ID)
curl --header "Private-Token: [PRIVATE_TOKEN]" "https://gitlab.com/api/v4/projects/[PROJECT_ID]/protected_branches" > branch-protection.json
- 获取 CODEOWNERS 配置:
curl --header "Private-Token: [PRIVATE_TOKEN]" "https://gitlab.com/api/v4/projects/[PROJECT_ID]/repository/files/.gitlab%2FCODEOWNERS/raw?ref=main" > codeowners-audit.txt
7.2 审计 checklist
- 角色权限检查:确认离职人员账号已从仓库移除(查看
Members列表); - 分支规则检查:确认
branch-protection.json中无冗余规则(如旧分支feature/old-*仍有保护); - CODEOWNERS 检查:确认
codeowners-audit.txt中角色账号未失效(如@web-reviewer已离职,需替换); - MR 记录检查:查看近1个月 MR,确认无“绕过审核合并”的情况(GitLab 仓库 → Merge requests → 筛选“Merged”,检查审核记录)。
7.3 审计结果同步
将审计报告(含问题与整改措施)通过企业 IM 同步给架构师与团队负责人,确保问题及时解决。
八、步骤7:常见问题与解决方案
| 问题场景 | 原因分析 | 解决方案 |
|---|---|---|
| CODEOWNERS 不生效,MR 无自动审核人 | 1. 文件路径错误(如 GitHub 用了 .gitlab/CODEOWNERS);2. 分支保护未勾选“Require approval from code owners” | 1. 确认文件路径正确(GitHub:.github/CODEOWNERS;GitLab:.gitlab/CODEOWNERS);2. 进入分支保护规则,勾选“Require approval from code owners” |
| CI 目录校验误判(合法文件被阻断) | 正则表达式错误(如允许目录少写 /,导致匹配失败) | 修正 allowed_dirs 正则,如将 ^apps/web 改为 ^apps/web/(确保匹配目录下所有文件) |
开发者无法创建 feature 分支 | 分支保护规则中“Allowed to push”未添加该角色 | 进入对应 feature/* 分支保护规则,将开发者账号添加到“Allowed to push”列表 |
九、操作后效果总结
方案核心概括
| 保护维度 | 具体措施 | 核心目标 |
|---|---|---|
| 核心分支锁死 | main/develop分支添加.gitlab/CODEOWNERS文件级保护,仅允许架构师+工具链开发修改/合并 | 禁止普通角色触碰核心规则 |
| 规则自保护 | CODEOWNERS内添加自引用配置,修改自身需双人审核(架构师+工具链开发) | 避免单一角色篡改规则 |
| 非授权分支阻断 | CI脚本拦截feature/*分支修改CODEOWNERS,触发即失败 | 防止通过功能分支绕过规则 |
| 权限最小化 | 仅授权2个必要角色(架构师+工具链开发),禁用强制推送 | 减少可修改角色,降低风险 |
| 事后追溯 | 每周用Git命令/GitLab日志审计CODEOWNERS修改记录 | 确保所有变更可追溯 |
| 紧急流程 | 仅通过hotfix分支修改,需双人审核+同步归档 | 兼顾安全与紧急场景效率 |
通过“核心分支文件级保护+规则自审核+CI拦截非授权分支+最小化授权+定期审计”,仅允许架构师与工具链开发双人操作.gitlab/CODEOWNERS,杜绝未授权修改。
通过以上7个步骤,sichuanji-cc 项目实现了:
- 角色-分支-目录的精准绑定:Web Dev 仅能操作
feature/web-*与apps/web,Admin Dev 仅能操作feature/admin-*与apps/admin; - 跨目录修改100%阻断:通过 CI 脚本与 CODEOWNERS,确保开发者无法误改非职责目录;
- 共享层变更多角色审核:
packages/auth/database等高风险模块变更,需核心开发+架构师+运维三方审核,避免安全隐患; - 权限可审计、可追溯:定期审计确保权限配置不过时,MR 记录可追溯所有变更的审核流程。
最终,该配置与项目的 npm workspaces + Turbo 技术栈协同,既保留了 Monorepo“共享复用、统一构建”的优势,又解决了“权限混乱、误操作”的痛点,为项目后续迭代提供安全保障。
以上操作步骤已覆盖从基础配置到验收审计的全流程,你可根据项目实际使用的 Git 平台(如 GitHub)微调操作路径(文中已标注 GitHub 与 GitLab 的差异)。若在实操中遇到特定场景(如新增 apps/mobile 模块后的权限扩展),或需要优化 CI 脚本适配项目现有构建流程,欢迎随时提出,我可进一步补充针对性方案。