Gitee 仓库治理
很多团队把代码迁到 Gitee 后,只做了三件事:建仓库、加成员、把默认分支叫作 main。这能让代码流动,却没有回答最重要的问题:谁能改关键分支,谁必须评审,新增提交后旧结论是否仍可信,外包成员离场后哪些入口仍然有效,以及平台版本或套餐变化时哪些门禁会消失。
Gitee 仓库治理不是“打开保护分支”这一个按钮。保护状态、推送权限、合并权限、PR 审查、测试门槛、CODEOWNERS、成员角色和企业级审计必须形成一条可验证链路。只配置其中一环,页面看起来很严格,真实 Git push 仍可能绕过去。
先建立一条可信的协作基线
不要在核心仓库里第一次试保护规则。先创建一个与业务隔离的仓库,并准备两个不同账号:
repository-admin:仓库管理员,配置规则、成员和合并;developer:普通开发者,创建分支、push 和发起 PR。
如需验证 Fork + PR,再准备一个不在源仓库中拥有写权限的贡献者账号。不要由同一管理员账号同时扮演开发者和审查者;高权限账号会让许多负向测试天然通过,最终得出错误结论。
本机安装 Git,并确认远端和身份配置:
git --version
git config --show-origin --get user.name
git config --show-origin --get user.email
git remote -v示例统一使用 https://gitee.example.com/example-org/repository-governance-lab.git 作为占位远端。Gitee.com 的真实地址、企业私有域名、个人邮箱、access token、SSH 私钥和代理凭证不得写入仓库。若企业要求提交邮箱与账号一致,应使用测试账号的已验证邮箱,不要复制个人真实邮箱到公开文档。
开始配置前,记录产品形态、套餐、界面版本和仓库可见性。Gitee.com、Gitee 企业版与私有化产品可能采用不同的角色名、设置入口和能力组合。看不到某个入口时,应先核对当前授权,再由低权限账号验证真实行为,不能根据另一种产品形态的截图推断结果。
Gitee 的保护分支说明明确了关键分支修改与合并的限制入口;评审模式说明进一步区分了拒绝直推与把直推转换为 Pull Request 的两种行为。Pull Request 代码审查流程、CodeOwners 规则和企业仓库成员权限表分别约束审批过程、路径责任人与角色能力。它们必须组合验证:页面中出现某项功能,不等于当前账号、仓库类型和套餐已经得到相同能力。
Gitee 仓库治理无需安装额外客户端,基础入口仍是 Git 与 Web 页面。先不加复杂规则,跑通一个最小 PR,建立正常路径基线。
Developer 克隆测试仓库并创建功能分支:
git clone https://gitee.example.com/example-org/repository-governance-lab.git
cd repository-governance-lab
git switch -c feature/pr-smoke
printf "pull request smoke test\n" > governance-smoke.txt
git add governance-smoke.txt
git commit -m "test: verify pull request path"
git push -u origin feature/pr-smoke在 Gitee 页面创建 Pull Request,目标分支选择 main。描述应说明改动目的、验证方式、风险和回退;审查者在“文件改动”中查看 diff、留下行级评论并通过审查,具备合并权限的人再合并。若启用了测试人员或其他门槛,还要分别完成相应状态,不能把“评论说没问题”当成平台已记录的通过。
合并后验证:
git fetch --prune origin
git log --oneline --decorate -5 origin/main
git ls-remote --heads origin feature/pr-smoke预期 origin/main 包含合并结果,源分支按团队策略删除或保留。若连普通 PR 都不能创建,先排查仓库可见性、成员角色、源/目标分支、Fork 关系和凭证,不要立即开启更多门禁。
保护分支:先选清楚标准模式还是评审模式
进入仓库管理中的保护分支设置,为 main 建立规则。不同产品版本的字段名称可能不同,但必须明确回答:谁能 push,谁能 merge,是否允许 force push,采用标准模式还是评审模式,PR 需要哪些审查/测试条件。
两种模式的行为差异决定了开发者看到的故障:
标准模式:没有推送权限的用户向保护分支 push 时,远端拒绝。适合希望开发者显式创建功能分支和 PR、避免意外目标分支的团队。评审模式:没有推送权限的用户向受保护分支 push 时,平台可自动创建或更新 PR。它减少手工步骤,但 push 的目标分支、生成的源分支/PR、描述质量和后续清理必须纳入团队规范。
无论选择哪种模式,规则都必须真正绑定并启用在目标分支。仅填写审查人或在文档中声明“main 是保护分支”,不会形成 Git 接收门禁。
先以标准模式做最清楚的负向实验。Developer 在本地 main 创建测试提交:
git switch main
git pull --ff-only
printf "direct push must be controlled\n" >> governance-smoke.txt
git add governance-smoke.txt
git commit -m "test: direct push protection"
git push origin main预期远端明确拒绝。把本地提交移到功能分支继续走 PR:
git switch -c feature/protection-negative-test
git push -u origin feature/protection-negative-test若使用评审模式,则成功标准不是简单的“push 失败”。应在页面看到平台自动创建或更新了对应 PR,目标仍是受保护分支,而且在审查/测试门槛满足前不能合并。团队必须为两种模式保存不同的预期结果,避免把评审模式的正常行为误报为保护失效。
配置 PR 审查:把讨论、通过与合并分开
PR 页面上的评论、审查通过、测试通过和最终合并是不同动作。仓库管理员应在代码审查设置中指定审查者/测试者及合并门槛,再用真实 PR 验证:
Developer 能创建 PR,但不能因自己是作者就完成全部门槛;审查者能查看 diff、评论和标记审查结果,但不一定拥有合并权;新 commit 进入 PR 后,已阅文件和必要审查状态按当前产品规则重新评估;
只有满足保护分支、审查、测试和合并权限的人才能完成合入。
Gitee 官方“代码已阅”说明,新代码变更会取消对应文件的已阅状态。已阅用于保存阅读进度,不等同于审查通过。团队不能把“所有文件已阅”当成唯一审批证据,也不能把一条“LGTM”评论当成结构化审查状态。
验证更新行为时,先让审查者查看并通过,再由 Developer 追加提交:
git switch feature/protection-negative-test
printf "review must cover latest diff\n" >> governance-smoke.txt
git add governance-smoke.txt
git commit -m "test: update pull request after review"
git push返回 PR 页面,确认变更文件的已阅状态、审查/测试状态和可合并状态符合团队要求。若平台当前版本不会自动使某类结论失效,团队应增加“最后审批必须晚于最后 push”的操作规则或外部门禁,并明确它是补偿控制,而不是声称平台已经阻断。
用 CODEOWNERS 自动找到正确的人
在仓库根目录、.gitee/ 或 docs/ 中创建 CODEOWNERS。文件只对它所在的当前分支生效,因此应确保受保护目标分支上存在正确版本:
# 默认责任人
* @default-reviewer
# 身份与权限配置
/config/auth/ @security-reviewer
# 数据变更
/database/migrations/ @data-reviewer
# 文档目录下一层文件
docs/* @docs-reviewerGitee 的匹配有几个容易误判的细节:
同一文件命中多条规则时,最后匹配的模式决定 owner;owner 可以写用户名或邮箱,但真实团队优先使用平台账号,避免邮箱泄露与离职漂移;指派对象必须存在并具备仓库开发者以上角色;企业超管、管理员或组织管理员如果不是仓库成员,并不会仅凭全局身份自动成为可指派 owner;
owner 无效或角色不足时,平台可能不提供清晰的“为什么未指派”提示;已经由旧规则指派的 PR,在 CODEOWNERS 减少成员后可能保留历史指派,需要人工确认当前责任。
建立三个小 PR 分别修改普通文件、config/auth/、同时修改认证和数据目录。预期自动指派与最后匹配规则一致。再把某个 owner 临时降为低权限测试账号,验证平台是否停止指派并记录观察结果;测试后立即恢复。不要在真实仓库用离职员工做实验。
CODEOWNERS 解决的是“自动找谁”,保护分支和代码审查设置解决的是“是否必须得到同意”。若当前产品/套餐只提供自动指派而不能把 owner 批准设为不可绕过门槛,文档中必须如实写成辅助控制,并由固定审查规则补齐。
由 Repository Admin 完成配置,再由 Developer 执行四条黑盒路径。每条路径同时记录 Git 远端结果和 PR 页面状态:
正常路径:向 feature/verify-normal push 并创建目标为 main 的 PR。预期功能分支可写,完成规定的审查和测试后才可由授权角色合并。保护分支路径:向 main push。标准模式应明确拒绝;评审模式应创建或更新 PR,并继续受审查门槛约束。两种结果都不能被含糊记录为“保护成功”。CodeOwner 路径:只修改一个受控目录。预期指派最后匹配规则中的有效 owner;修改不受控测试目录时,不应错误指派该 owner。
更新路径:审查者完成已阅和审查后,Developer 再修改同一文件并 push。预期平台状态或团队补偿门禁要求对最终 diff 重新确认。
每条路径都要记录产品形态、套餐/版本、执行角色、分支模式、远端输出、PR 状态和最终 commit 标识。完成后关闭未合并 PR、删除测试分支并恢复临时角色。只有目标租户上的双账号结果,才能证明实际规则与团队期望一致。
角色与权限
Gitee 企业仓库可出现访客、报告者、观察者、开发者、管理员等角色,社区版、组织仓库和私有化版本的命名与能力可能不同。不要从角色名字猜权限,应从目标版本的成员权限表和实际账号验证。
一套常见职责分离是:
只需跟踪事项的人不获得源码写权限;需要读取私有代码但不提交的人使用只读类角色;日常研发使用 Developer,只向普通分支 push 并创建 PR;
审查者获得完成审查所需角色,但不因此自动获得仓库管理权;少数 Repository Admin 管理规则和成员,合并权再按分支保护单独收紧;企业管理员管理企业级策略,不把全局身份当作每个仓库的日常操作账号。
外包或临时成员应设置明确结束时间,使用独立账号并限制到所需仓库。离场不只删除企业成员,还要检查仓库直接成员、组织/团队继承、Fork 可见性、部署公钥、访问令牌、Webhook 和自动化账号。共享“项目开发账号”无法回答是谁 push 或审批,应禁止使用。
对存量仓库不要一次性打开所有限制。建议按以下顺序落地:
盘点默认分支、成员角色、分支保护、审查/测试人、机器凭证和历史直推方式。跑通普通 PR,统一描述、评审与合并证据,先让团队熟悉正常路径。将关键分支设为保护状态,选定标准或评审模式,用 Developer 做直推负测。
增加审查和测试门槛,验证作者、审查者、测试者与合并者的职责边界。提交 CODEOWNERS,从一两个高风险目录开始,验证最后匹配和无效 owner 行为。将规则期望、产品形态、套餐缺口、例外和 owner 写入治理清单。
一个迭代后再收紧次要分支,并对所有存量仓库做 drift 复核。
仓库中适合保存 CODEOWNERS、PR 模板、贡献说明和不含凭证的规则说明。平台权限和保护规则仍要通过界面或受控 API 读取实际值。文档是期望状态,不是运行状态;只有双账号黑盒验证才能证明它们一致。
Gitee API 调用使用独立、最小 scope、可过期的访问令牌。脚本读取环境变量或凭证系统,不把 token 写入 URL、源码、日志和命令示例。批量修改成员或保护规则前先导出旧值,在测试仓库演练,并给存量仓库分批执行与回退窗口。
迁移先区分 Git 对象与平台治理数据
迁移或建立异地副本时,可以先用 Git 原生命令保存全部 refs:
git clone --mirror https://gitee.example.com/example-org/repository-governance-lab.git
cd repository-governance-lab.git
git show-ref
git fsck --full
git push --mirror https://git-target.example.com/example-org/repository-governance-lab.git--mirror 会处理分支、标签和其他 refs,却不会自动搬走 Pull Request 的审批记录、评论、Issue、Wiki、成员关系、保护规则、Webhook、部署公钥、Token、审计记录和套餐能力。若当前产品提供仓库镜像入口,Gitee 的仓库镜像说明仍把同步对象限定为分支、标签和提交,并提示双向镜像、LFS 与覆盖目标 refs 的风险;入口是否继续开放及适用套餐必须在目标租户确认。迁移方案必须把 Git 数据、协作数据、身份权限和外部集成拆成四张清单,逐项确认导出入口、导入能力、只读窗口与责任人。
切换前冻结旧仓库写入,记录最终 source SHA 与 tag 数量;切换后在目标平台重建保护规则和最小权限,用普通开发者重跑直推失败、PR 成功、CodeOwner 指派和旧凭证失效。旧平台只读保留期结束前,不删除唯一的 PR、审计或权限证据。托管服务承担基础设施可用性,不替团队决定保留周期、迁移完整性和误删后的业务恢复目标。
同仓库协作适合稳定团队成员:
git fetch origin
git switch -c feature/<topic> origin/main
# 修改并完成本地验证
git push -u origin feature/<topic>Fork + PR 适合开源贡献、外部协作者和不应获得源仓库写权限的人。Fork 会引入同步、来源分支删除和可见性边界;不要仅为了形式统一要求所有内部成员 Fork,也不要为了少一步操作给所有外部人员 Developer 权限。
评审模式适合希望保留“直接向目标分支 push”的命令习惯、又要求平台自动转成 PR 的团队,但它会隐藏源分支命名和 PR 描述步骤。标准模式让失败更明确,开发者必须显式创建功能分支。二者没有绝对优劣,选择标准是团队能否清楚解释 push 后发生了什么、如何关联工作项、如何更新 PR、如何清理自动分支。
紧急修复仍优先使用短期分支和 PR。确需临时改保护规则时,必须记录事件号、批准人、时间窗、变更前值、变更后值、操作人、审计证据和恢复验证。不要长期保留“管理员可直推,所以应急有保障”这种旁路。
HTTPS 与 SSH 是两条不同链路
浏览器能打开 Gitee 不代表 Git HTTPS 或 SSH 能连通。HTTPS 排查配置来源:
git config --show-origin --get-regexp 'http\..*proxy|http\.proxy|http\.sslCAInfo'SSH 只在受控环境输出详细日志:
ssh -Tv git@gitee.example.com企业 CA 应安装到系统信任库或通过 http.sslCAInfo 指向批准证书链,不设置 http.sslVerify=false。代理用户名和密码不写进 remote URL 或 .gitconfig 明文;使用系统凭据库、Git Credential Manager、SSH agent 或企业网络代理的受控注入。
PAT 不是 Git 密码的永久替身
个人 access token 只授予当前操作所需权限,设置到期时间并保存到凭据管理器。SSH 私钥为个人独有,不通过聊天、压缩包或仓库共享。离职时同时撤销 token、SSH key、会话和应用授权,而不是只把成员移出仓库。
机器任务使用独立机器人账号、部署公钥或目标产品支持的机器凭证。它只向普通分支 push 并创建 PR,通常比直接写保护分支更容易审计。若机器必须拥有合并或管理权限,应记录不可替代的原因、限制范围、轮换周期和失败回退。
权限异常先找继承和身份
同一个人可能同时从企业、组织、项目、仓库和直接成员关系获得能力,实际身份还可能被本地凭据缓存替换。遇到“明明降权还能 push”,先用平台页面确认当前登录账号,再清点所有成员来源、SSH key/token 所属账号和保护分支允许对象。不要用删除本地 Git 缓存作为唯一修复,它不会改变服务端授权。
现象一:配置了审查人,Developer 仍能直推 main
用 Developer 对 main push 一个无害测试提交,查看分支是否实际处于保护状态以及 push/merge 允许角色。
常见原因:只配置了代码审查,没有启用保护分支;保护规则匹配了错误分支;Developer 或其继承角色仍有推送权;使用了管理员/机器人凭证而不是 Developer 身份。
启用并绑定正确保护规则,收紧推送权限,核对标准/评审模式和实际凭证。审查设置不替代 Git 接收权限。
标准模式下直推被拒绝;评审模式下自动生成或更新 PR 且无法越过审查门槛;普通功能分支仍可 push。
现象二:修改目录后没有自动指派 CodeOwner
查看目标分支上的 CODEOWNERS,从文件末尾向前确认最后一条匹配规则,再核对 owner 是否为仓库成员及其角色。
常见原因:文件在源分支而不在目标分支;放置位置或大小写错误;后面的通配规则覆盖了前面的精确规则;用户名不存在;用户不是仓库成员或低于 Developer。
将文件放到官方支持位置,调整规则顺序,使用有效平台账号并授予完成评审所需的最小角色。不要改用真实邮箱来掩盖成员关系错误。
分别创建只改普通文件和只改目标目录的小 PR,确认指派不同且日志可见。
现象三:PR 更新后仍沿用旧评审结论
比较最后 push 时间、最后审查时间、文件已阅状态、审查/测试状态与当前 diff。
常见原因:把已阅、评论和审查通过混为一谈;平台当前规则只重置部分状态;新增 commit 未触及已阅文件;团队没有规定最后审批必须覆盖最终 commit。
启用目标产品可用的重置机制;不足处增加“审批 commit SHA/最后 push 后复审”的补偿规则。高风险仓库可要求合并者核对最终 commit 标识。
先通过,再修改已审文件并 push,确认相关已阅/审批状态失效或补偿门禁阻止合并。
现象四:评审模式下 push 没有生成 PR
确认分支确实受保护且模式为评审模式,push 身份没有该分支推送权限,检查页面是否已有同来源分支 PR。
常见原因:误用了标准模式;用户本身有推送权限,因此平台直接接受;规则未命中;凭证对应另一个高权限账号;自动 PR 已存在但被过滤或关闭。
修正规则与账号,先用明确的低权限测试身份和唯一测试分支复现。不要通过给 Developer 更高权限来“修复自动 PR”。
第一次 push 创建 PR,第二次 push 更新同一 PR,审查门槛持续生效。
现象五:离职成员已移除,机器任务仍能写仓库
列出仓库/组织成员、部署公钥、access token、机器人账号、Webhook 和第三方应用,按最近使用时间和 owner 对账。
常见原因:自动化使用共享账号或离职者 token;部署公钥仍可写;成员从其他团队继承;外部系统缓存了长期凭证。
撤销旧入口,创建归属团队的机器身份,最小授权并轮换;更新任务后验证旧凭证失败。不要把个人账号改名为“机器人”继续使用。
新身份只能完成批准路径,旧 token/key 无法访问,审计能定位新身份操作。
架构取舍:社区版、企业版与私有化
Gitee.com 社区版适合开源项目、个人和轻量协作,运维成本低,但企业级角色、审查策略、审计、组织治理和配额以当前产品开放范围为准。企业版提供更完整的组织、权限、代码审查和审计能力,但具体套餐、人数和功能限制必须在采购与续费时重新核验。私有化适合有内网、数据驻留、版本窗口或深度集成要求的组织,同时带来升级、安全补丁、备份、容量、审计存储和灾备责任。
选择平台形态时,不要只比较“有没有保护分支”。至少维护一张能力验证矩阵:低权限直推阻断、PR 审查与测试门槛、CodeOwners 是否仅指派还是可强制、成员继承、机器凭证、审计事件、导出/API、SSO/离职回收、网络与合规边界。每项都标记目标版本的实际结果,而不是复制产品介绍。
仓库内协作与 Fork 协作也属于架构选择。前者反馈快、分支统一,适合受信任内部团队;后者隔离写权限,适合开源和外部贡献,但增加同步与可见性管理。外包项目可以基于独立仓库和 Fork 模型收紧边界,不能只靠“外包成员”标签获得隔离。
“保护”一词掩盖了模式差异
标准模式强调拒绝,评审模式强调把无权 push 转为 PR。如果监控或培训只写“保护分支会拒绝 push”,评审模式会被误判为故障;如果只写“push 会自动建 PR”,标准模式用户又会不断重试。团队必须把模式、预期远端输出、页面状态和清理动作绑定在一起。
CodeOwners 的静默失配比语法报错更危险
不存在的账号、角色不足、后续规则覆盖和目标分支版本错误,都可能让指派没有发生,却不一定给出足够醒目的错误。治理巡检应扫描无效 owner,并用代表性路径创建测试 PR。只 lint 文件语法不够,因为成员关系是平台运行时状态。
企业权限存在多层继承和产品差异
企业角色、项目角色、仓库角色、组织关系和直接成员可能叠加。迁移或升级后,角色名相同也不保证能力完全相同。升级前后要用角色矩阵做黑盒测试:读取、clone、普通分支 push、保护分支 push、创建 PR、审查、测试、合并、改规则、加成员,各动作分别记录允许或拒绝。
审计能力必须在事故前证明可用
产品页面宣称有安全审计,不等于当前套餐能记录和导出团队需要的全部事件。应主动完成一次演练:添加测试成员、修改保护规则、创建并合并 PR、撤回临时权限,然后确认能查到操作人、时间、对象和结果。缺失事件要通过企业日志、身份系统或变更单补偿,并明确留存周期和访问权限。
国内网络稳定不等于凭证与代理可以简化
企业代理、SSL 解密、私有化域名和多账号仍会造成浏览器、Git HTTPS、SSH 与 API 四条链路行为不同。禁止以关闭 TLS 校验、共享 PAT、把 token 写入 URL 或所有人共用 SSH key 作为“网络兼容方案”。这些做法会直接破坏审计归属。
至少明确仓库 Owner、规则 Owner、身份凭证 Owner 和审计 Owner。仓库管理员负责操作不代表独自拥有所有决策权;关键规则变化应由业务与平台双方复核。CODEOWNERS 中每个高风险目录至少有两个可用责任人或明确替补,避免休假、转岗后 PR 永久阻塞。
新增仓库应从批准模板建立,但仍要执行三项黑盒验证:Developer 对关键分支的预期行为、敏感目录 CodeOwner 指派、PR 新提交后的状态变化。季度巡检成员与继承关系、保护模式、审查/测试人、无效 owner、长期 token/key、管理员例外、审计可用性和套餐变化。
私有化升级、企业版续费或组织迁移前,先导出当前规则与成员矩阵,在测试环境复演关键路径。升级后再跑相同实验。发现能力变化时,应显式记录治理降级、替代控制与修复期限,不让规则在界面迁移中静默失效。
清理测试仓库
实验结束后关闭未合并 PR,删除测试功能分支,恢复临时调整的成员角色和保护规则。只清理本次测试对象,不删除共享组织、真实默认分支、企业级审查人或全局凭证。
git push origin --delete feature/protection-negative-test
cd ..
# 删除本地目录前确认它是本次独立测试仓库保留脱敏验证证据:产品形态/套餐/版本、规则摘要、执行角色、标准或评审模式、允许与拒绝结果、PR 编号占位引用和清理结果。不要保留真实 token、私钥、邮箱、代理密码或内部地址。
已记录 Gitee.com 社区版、企业版或私有化形态、套餐与版本,不混用不同产品结论。关键分支已真正处于保护状态,push、merge、force push 与标准/评审模式均有明确值。已用普通 Developer 验证:标准模式直推被拒绝,或评审模式自动生成/更新 PR。
PR 的评论、已阅、审查通过、测试通过和合并权限没有被混为同一证据。已验证新提交进入 PR 后,平台状态或团队补偿门禁覆盖最新 commit。CODEOWNERS 位于目标分支的支持路径,最后匹配规则符合预期,owner 是有效仓库成员且角色足够。
已明确 CodeOwners 在当前产品中是自动指派还是强制门禁,没有夸大能力。成员权限已按实际动作验证,并检查企业、组织、项目、仓库和直接成员的继承关系。HTTPS、SSH、API 与浏览器链路分别验证,企业 CA 可用且没有关闭 TLS 校验。
个人 PAT/SSH 与机器凭证分离,token 有最小权限、到期和轮换演练。外包与离职回收覆盖成员、Fork、token、部署公钥、机器人和第三方应用。规则例外有批准、时限、审计、恢复和低权限再验证。
审计演练能找到成员变化、规则变化和关键 PR 操作,缺口有替代控制。测试 PR、分支、角色和临时规则已清理,没有影响真实仓库历史。
