为什么要多这几道手续
麻烦是真的,值不值是另一回事——先看清多出来的手续在买什么。
你已经知道怎么做了:拉一条分支,改完提交,推上去,开一个合并请求,等检查跑完,等人看过,合并。
问题是走到第三天,一定会冒出一个念头——改一行字也要走这一整套,这不是折腾吗?
这个念头很合理。这一页不打算说服你它不麻烦,它就是麻烦。这一页只回答一件事:多出来的这几道手续,到底在买什么。
一、这不是谁拍脑袋想出来的土办法
先说来路,因为来路决定了你要不要认真对待它。
改动 → 有人看 → 批准 → 才进主干——这个形状不是某家公司的内部习惯,是几家把「很多人改同一批东西」这件事做到极限的机构,各自独立收敛出来的同一个答案。
- Google 的做法是:任何人都可以提出改动,但必须由这块地方的责任人点头,才能进主干。责任人写在一份目录清单里,谁负责哪块一目了然。
- Meta 走的是把一个大改动拆成一串小改动、一层叠一层分别送审的路子,并把配套工具开源了出来。
- 公开的代码托管平台后来上线的「叠放式合并请求」预览功能,是把大厂内部这套做法反向搬回了公开工具——一个内部做法能反流回公开产品,本身就说明它还是主线,不是过时的老规矩。
所以当有人说「这是大厂那一套,我们用不上」时,准确的说法是反过来的:正因为它在最复杂的场景里被反复验证过,它的默认形态才被削得很轻——轻到两个人的团队也能用。这一条下面第四节会给数字。
二、它的本体是知识传递,不是抓 bug
这是全页最该记住的一句。
Google 公开发表过一份针对自家代码审查的实证研究(《Modern Code Review: A Case Study at Google》,ICSE-SEIP),样本是约九百万次改动。结论出乎很多人意料:
当初引入这套流程的首要原因,是让代码更容易被读懂、更容易被维护。抓错是副产品,不是目的。
原始表述更直白——「逼开发者写出别人看得懂的东西」,以及那句被反复引用的:
代码必须充当未来开发者的老师。
这句话值得停一下。它说的不是「代码要写注释」,而是:这份东西本身要能教会下一个接手的人。而「有人会看、看不懂会问」这个机制,是唯一能持续逼出这个结果的东西——没有人看的时候,谁都会写得只有自己看得懂。
那它跟「走个形式」的区别在哪?
区别在产物。走形式的产物是一句口头的「行,你合吧」;这套流程的产物是一段带存档、挂在这次改动旁边、半年后还能翻出来的书面判断。前者随人走,后者留在东西上。
而这正是我们做这一整套内容的原因:用可以留存的介质传递思维,替代靠人在场传递思维。「代码要充当未来开发者的老师」和这句话,说的是同一件事。
三、先说难听的:这是投资,回报滞后
这一节放在前面,不是为了铺垫,是为了在你抱怨之前先把话说了。
你会觉得烦,是真的,而且是预期之内的。
因为这套流程最大的两个收益,当期一个都不兑现:
- 第三个人加入的时候——他能靠翻历史看懂前因后果,而不是拉着你问三天。
- 半年后回头查的时候——你能查到「当时为什么这么改」,而不是对着一堆自己写的东西发呆。
这两件事,今天都不会发生。今天发生的只有:你要多等一会儿。
这里有个很实际的东西要交给你:同一份体验,归因不同,结局相反。
- 没人提前说过 → 你第三天的念头是「这套东西不好用」→ 放弃,并且从此认为方法有问题。
- 提前说过 → 你第三天的念头是「我还在投资期」→ 撑过去,然后在第三个人进来那天拿到回报。
而归因方式是在第一天被设定的,不是在你烦的那一刻。 所以这一节必须放在这儿。
四、它本来就是轻的,重是因为用错了
「大厂那套太重」是最常见的一个误解。看一眼那份研究里的真实形态(同一份样本,数字不做改写):
| 项 | 实际值 |
|---|---|
| 一次改动的行数 | 中位数 24 行 |
| 只改一个文件的改动 | 超过 35% |
| 只改一行的改动 | 超过 10% |
| 一次改动的审阅人数 | 中位数 1 人 |
| 从提出到走完的耗时 | 中位数不到 4 小时 |
也就是说,它的默认形态是:小、快、一个人看。
那什么时候会变重?
攒大了的时候。一次塞进去几百行、跨好几块地方,审的人得先花半天搞懂你在干嘛——于是拖,于是堵,于是有人开始绕过它。
而流程一旦被绕过一次,就会被绕过第二次。这是这套东西真正的失效路径——不是它太重,是它被攒重了,然后被放弃了。
五、九个环节,每一环在买什么
前面讲的是「为什么值得」。这一节把它落到地上:每一环技术上在干什么、通俗怎么说,以及——最容易讲错的地方在哪。
第三列是这张表的重点。这九处误解,是我们在真实带教里一次次撞出来的,不是想出来的。
| 环 | 通俗说 | ⚠️ 最容易讲错 |
|---|---|---|
| ① 建分支 | 不是复印项目,是在时间线上放个书签,从这里另起一条支线 | 以为建分支=复制整个项目,因而「不敢建」。实际上系统只记差异,建分支近乎零成本 |
| ② 改文件+提交 | 保存是给自己看的;提交是给别人、和给半年后的自己看的 | 把提交等同于「保存」。区别在于它强制你写一句「为什么」——「代码要充当未来开发者的老师」第一次落地就在这一格 |
| ③ 推送 | 提交之前,东西只在你自己机器上;推送之后别人才看得见 | 以为提交完别人就看到了。这套系统默认是离线的、本地的,这是它和云端文档最大的区别。(在网页上操作时,提交与推送合并成一个动作) |
| ④ 开合并请求 | 不是交东西,是交申请——东西在推送那步就已经上传了 | 把它说成「上传代码」。合并请求里没有任何新内容,它只是一个请求加一个讨论区。★ 请求描述那一格,就是写给未来读者的那封信 |
| ⑤ 自动检查跑起来 | 找一台完全不认识你的机器,从零把你的东西装一遍 | ⚠️ 最贵的一条误解:以为检查通过=功能正确。自动检查通常只验「装不装得起来」,完全不验业务对不对。把文案改成一句废话它通过,改成一串乱码它照样通过。检查挡的是「跑不起来」,不是「做错了」;做错了靠人看挡。 |
| ⑥ 审阅 | 不是查错别字,是问「这件事该不该这么做」 | 说成「检查有没有 bug」。九百万次改动得出的结论是:首要目的是可理解性与知识传递,抓错是副产品 |
| ⑦ 合并 | 申请批准,改动进入主线 | ⚠️ 合并 ≠ 上线。点完合并主干确实变了,但打开线上还是老样子——正在跑的是之前构建出来的成品,它不会自己去拉新的。(这个词在概念词典里有词条,点过去看) |
| ⑧ 部署 | 把仓库里的图纸,变成服务器上真在跑的东西 | 以为部署会自动发生。它通常是要人去做的。另外,不同形态的应用部署方式不同——有的构建完就生效、没有中断;有的必须重启进程,会有一小段停机 |
| ⑨ 看线上 | 验收落在人眼睛看得见的地方 | 拿「构建日志成功」或「接口返回正常」当验收。★ 验接口不等于验产品——接口全绿而页面什么都没渲染出来,是真实发生过的事。验收判据必须落在界面上的一个动作。 |
给刚上手的人一条实际建议
改动只涉及一个文件的小改时,在网页上直接操作比拉到本地更好——每一环在界面上都是一个独立按钮,形状最清楚。拉到本地的四个真正价值(本地跑起来、批量改、断网也能改、用本地工具),这时候一个都用不上。
两遍法:第一遍在网页上学形状;第二遍拉到本地,补上「本地副本」这一环。第一遍合并之后,你本地那份必然是落后的——第二遍开工前必须先拉一次。 这个落后是故意留给你的:在真实的别扭里学会它,比被口头告知一遍记得牢。
六、闸,还是自觉
到这里,「为什么值得」讲完了。但还剩最后一个问题,而它比前面所有问题都重要:
这些规矩,是靠人自觉执行,还是靠机器强制执行?
没有闸的时候,系统对下面这些动作一律不拦:跳过合并请求直接推主干(不拦)/该批的人没批、自己点了合并(不拦)/自动检查亮着红叉、照样能合并(不拦)/改了别人负责的地方、没有人被通知(不拦)。
在这种状态下流程跑通了,证明的是「这个人很自觉」。它没有证明:他赶时间的时候、或者第三个人加进来之后,这套东西还立不立得住。
有闸的时候:直接推主干会被拒绝/没批准时合并按钮点不动/检查没过时合并按钮点不动/碰到别人负责的地方会自动把他加成必须审阅的人。
在这种状态下跑通,证明的才是「流程能兜住人」——想图快也做不到。
「人守规矩」和「规矩守人」是两回事:前者随人变,后者不随人变。
还有第三种状态,而它是最危险的那种
前面两种是教科书上的分法。下面这一种,是我们自己撞出来的。
我们给主干装了闸:自动检查被设成「必须通过才能合并」,分支保护也开着。设置页上,规则一条条列在那儿。
后来一位同事以「先复制一份仓库到自己名下,再从那份提合并请求」的方式参与协作——这是给权限较窄的协作者用的标准路子。她提的请求页面上,「等待检查结果」的字样也在。
看起来一切正常。
实际上:托管平台还有一个单独的开关,管的是「允不允许为这种从外部副本发起的请求运行自动检查」。那个开关,在组织层和仓库层,双双没开。
结果是:从这条协作路径建立那天起,那道自动检查一次都没有为她跑过。整道闸,从来没有生效过。
它比「根本没装闸」更危险,因为屏幕上看不出区别。 没装闸的时候,人知道自己在裸奔;这种状态下,人以为自己被保护着。
它为什么很久都没被发现
这一段值得完整看一遍,因为每一步单独看都是对的:
- 刚建起这条协作路径时,那次请求是纯文档改动,按当时的配置,自动检查本就不该跑——零检查是预期之内的,没人起疑。
- 后来有一轮去掉了「文档改动跳过检查」的配置——但那一轮修的是另一个洞。
- 再后来有一轮专门验证「纯文档改动也会触发检查」,用的是主仓自己的分支发起的请求——绿是真绿,但它绕开了「外部副本」这条路。
三轮各自都对。合起来,恰好没有一轮踩到「外部副本 + 触发」这个组合。
于是有了两条我们此后写死的规矩:
一、一道闸能不能拦住人,等于「规则 × 触发 × 没有例外」三者相乘——任何一个是零,整道闸就是零。而它坏掉的时候,长得跟正常一模一样。
二、验一道闸,必须沿着它真正要拦的那条路走一遍:谁的账号、哪一种请求、哪一个动作触发。任何替代路径上的绿,只能证明替代路径。
再补一条,因为它当时让我们绕了两次弯:像「等待检查结果」这种卡住不动的状态,成因至少有四层——请求本身的、流程配置文件的、仓库设置的、组织策略的。这四层在页面上长得一模一样。 所以看到一个开关是灰的,第一反应不该是「怎么点亮它」,而是「谁把它锁住了」。
这件事对「值不值」意味着什么
回到第三节那句「这是投资,回报滞后」。第三种状态补上了它的另一半:
不只是回报会滞后——你甚至可能连投资都没真正发生。
一个团队完全可能装了一整套流程、开了所有该开的选项、每次合并都看到「等待检查」四个字,而那道闸从第一天起就没有通电。
「我们有流程」和「流程在生效」是两件事,中间隔着一次真实路径上的验证。
最后一句诚实话:这一套确实有代价。两个人的团队会觉得仪式重;收益兑现得慢;而且你必须提前约定一条紧急通道——线上真出事的时候直接修,事后补上记录,并且明确它是例外、不是常态。只讲好处不讲代价,你第一次等审批的时候就会觉得被忽悠了。
七、下一步
想自己往下学
(这一页讲的是「为什么」,下面几页讲「怎么做」)
- 先看全景 → 《一张图看懂:两个人、一个仓库、互不踩脚》:那张图、四个常见的想错、三条铁律。
- 两个人怎么分工 → 《别共用一个账号:多人协作的架构与权限》。
- 不写代码的人怎么参与 → 《他不会写代码,但 AI 会》。
- 真走一遍会撞上什么 → 《第二个人进来那天:一次真实接入的全程实录》。
- 词不认识 → 概念词典里有「分支」「合并请求与合并」等词条,点过去看,这一页不重复定义。
想找我们一起做
这套形状不是代码专有的。你手上只要有「多个人在维护、会持续改、改错了有后果」的东西——话术库、提示词与 AI 配置、报价与参数表、作业流程文件、知识库文章——它都能套上去。每一环都可以整列替换:隔离可以是分支,也可以是一份草稿副本;申请可以是合并请求,也可以是一条走审批的提交;自动检查可以是构建,也可以是格式与禁用词扫描;审阅可以是逐行评论,也可以是一份审阅意见(但必须留下字,不能只点一个同意)。
认得出左边那一列,你换任何工具都能自己搭起来;绑死在某个工具上,工具一换就得重来。
如果你想看看这套形状放到你们的场景里该长什么样,。规模很小、东西很简单的时候,它可以退化成「一份共享文档开建议模式 + 一个人审」——形状不变,工具降级。