Git 与代码协作
周五下午,一个已经通过评审的分支又被强制推送。页面仍然显示两名成员批准过,流水线也曾经成功,但合并后的提交并不是评审者看到的那一版。与此同时,值班人员发现提交作者邮箱属于另一家公司账号,回滚时又把已经发布的 merge commit 当成普通提交处理,主干历史随即出现第二次事故。
这里没有哪一条 Git 命令特别难。真正困难的是多个状态系统同时参与协作:本地对象库记录提交,凭证系统决定谁能访问,签名系统证明谁持有某个密钥,托管平台保存审批和检查证据,分支规则决定哪些状态可以进入主干,审计日志再回答谁绕过了规则。只掌握 add、commit 和 push,无法解释这些系统之间的空隙。
一次 push 穿过了哪些边界
开发者执行 git push 时,至少有七层状态需要同时成立:
当前调用的是预期版本的 Git,配置没有被另一份系统级或条件配置覆盖。HTTPS 凭证或 SSH key 对应正确账号,代理和主机信任没有把连接导向错误目标。Commit、Tag 或合并对象表达了预期历史,作者身份与密码学签名没有被混为一谈。
推送目标、默认分支和远端跟踪关系正确,公共历史没有被无保护地改写。PR/MR 的审批、CODEOWNERS 和自动检查绑定到当前 head commit,而不是旧版本。平台分支规则、角色和绕过权限真正拒绝了不合规操作。
LFS 对象、submodule 指针、审计事件和迁移资产仍然可获取、可追踪、可恢复。
任意一层失真,都可能出现“命令成功但工程结果错误”。学习 Git 协作的目标不是背更多子命令,而是能指出当前证据属于哪一层、缺失哪一层,以及发生事故后应该先冻结哪个状态。
从本地基线进入团队协作
第一次接手项目时,先用 Git 安装、升级与配置 确认可执行文件、版本来源、配置作用域、换行策略和默认分支。它解决的是“这台机器上的 Git 究竟是谁配置的”。
随后选择实际认证链路:HTTPS、GCM 与凭证治理 适合借助系统凭证库和 OAuth/PAT 生命周期管理,SSH 认证、多账号与代理 则需要同时管理 key、agent、known_hosts、Host 别名和跳板路径。两条链路可以并存,但同一仓库必须能解释最终命中了哪个账号和哪份凭证。
Commit、Tag 签名与信任链 继续回答另一个问题:能够登录平台,并不等于提交对象已经由可信密钥签名。文章把作者字段、登录身份、SSH/GPG/S/MIME 签名、allowed signers、撤销和平台绿色标记拆开验证,避免把一种证据错误外推为完整身份可信。
历史不是一条线,而是一组对象关系
分支、merge、rebase 与 cherry-pick 从引用和 Commit 父节点开始。分支只是可移动引用,merge commit 有两个父节点,rebase 和 cherry-pick 会创建新对象;理解这些事实以后,才能判断某个操作是在移动名字、增加对象,还是重写别人已经依赖的历史。
冲突处理与 rerere 把冲突从编辑器里的红色标记还原成 index 的 stage 1/2/3。这里不仅要让文件“没有冲突”,还要证明共同基线、双方变化和最终业务语义都被保留。rerere 可以复用解法,却也可能稳定地复用一次错误决定。
撤销、恢复与公共历史回滚 区分工作区、index、引用和共享历史:restore、reset、reflog 与 revert 处理的对象不同。事故处理中先创建救援引用、记录 commit ID 和影响面,再决定恢复手段;已发布数据库、消息或外部副作用也不会因为 Git 回滚而自动消失。
评审页面必须变成可执行门禁
Pull Request、Merge Request、Review 与 CODEOWNERS 把审批绑定到具体 head SHA,并检查新推送是否使旧审批失效。CODEOWNERS 只负责找到责任人,必需审批、必需检查、直推限制、最新推送审批和绕过审计必须组合起来,才能让“已评审”成为可验证事实。
平台治理不能用一套截图复制到所有产品:
| 平台 | 深入路径 | 首先验证的事实 |
|---|---|---|
| GitHub | Rulesets、角色与审计 | 规则优先级、required checks、bypass actor 与环境部署权限 |
| GitLab | Protected Branch 与 Merge Request 治理 | push/merge 权限、approval tier、Code Owners 与 protected environment |
| Gitee | 保护分支与企业协作 | 两种保护模式、CodeOwners、Token、套餐能力与审计边界 |
| Gitea | 自托管仓库治理 | Unit 权限、保护分支、配置文件、备份恢复与版本差异 |
| Bitbucket Cloud | Workspace 与仓库治理 | branch restrictions、merge checks、workspace 权限和访问令牌 |
设置页面不是验收证据。至少需要维护者和普通开发者两个测试身份,用真实 push、审批失效、检查失败和绕过操作验证平台行为;同时记录套餐、版本和组织策略,因为相同界面在不同账户上可能并不提供相同强制能力。
仓库规模扩大后,问题会转移
二进制文件进入历史后,普通 clone 会同时承担所有版本的对象成本。Git LFS 用指针对象和独立 LFS 存储改变传输路径,因此必须一起治理对象可用性、权限、锁、迁移、配额、CI 下载和远端回收。只把文件写进 .gitattributes,并没有完成历史迁移。
Git submodule 用 gitlink 把外部仓库的精确 Commit 固定在父仓库中。它提供清晰的版本边界,也带来递归凭证、供应链信任、更新责任和删除残留。父仓库“最新”不代表子仓库工作区已经处于正确提交。
worktree、sparse-checkout 与 partial clone 分别处理并行工作区、工作树可见范围和对象下载范围。三者可以组合,却不是同一种优化:worktree 共享对象库但拥有独立 index,sparse-checkout 不会减少已经下载的对象,partial clone 则依赖远端 promisor 能力和工具兼容性。
把规则维护成工程资产
提交策略、审计与弃用治理 将本地 hook、commitlint、CI、服务端规则、签名和审计事件放进同一条证据链。本地 hook 能改善反馈速度,却可以被跳过;真正不能绕过的要求必须在服务端或合并门禁重新执行。例外也需要 owner、期限、影响面和关闭证据,不能靠永久管理员绕过维持交付。
团队可以从一个可删除的隔离仓库建立最小闭环:
git --version
git --exec-path
git config --list --show-origin --show-scope
git status --short --branch
git remote -v在隔离仓库中依次完成分支提交、推送、评审、保护分支拒绝、新提交导致审批失效、合并与回滚,再删除测试分支和临时凭证。生产仓库不承担第一次强推、签名撤销、merge commit 回滚或权限绕过实验。
团队自检
开发者能解释 Git 可执行文件、配置来源、认证账号和远端目标。HTTPS、SSH、提交签名和平台登录身份没有被当成同一种证据。merge、rebase、强推、冲突处理和公共历史回滚有明确团队规则。
审批与检查绑定当前 head SHA,普通成员无法直接更新受保护主干。管理员绕过有审计事件、使用条件、责任人和事后复核。LFS、submodule 和大仓库优化都有容量、权限、备份与退出方案。
Token、SSH key、签名密钥和机器人身份进入轮换与撤销流程。平台套餐、版本、API 弃用和规则漂移进入定期巡检。高风险实验使用隔离仓库,清理和恢复结果能够被另一名成员复核。
