为什么要多这几道手续

麻烦是真的,值不值是另一回事——先看清多出来的手续在买什么。

你已经知道怎么做了:拉一条分支,改完提交,推上去,开一个合并请求,等检查跑完,等人看过,合并。

问题是走到第三天,一定会冒出一个念头——改一行字也要走这一整套,这不是折腾吗?

这个念头很合理。这一页不打算说服你它不麻烦,它就是麻烦。这一页只回答一件事:多出来的这几道手续,到底在买什么。

一、这不是谁拍脑袋想出来的土办法

先说来路,因为来路决定了你要不要认真对待它。

改动 → 有人看 → 批准 → 才进主干——这个形状不是某家公司的内部习惯,是几家把「很多人改同一批东西」这件事做到极限的机构,各自独立收敛出来的同一个答案。

  • Google 的做法是:任何人都可以提出改动,但必须由这块地方的责任人点头,才能进主干。责任人写在一份目录清单里,谁负责哪块一目了然。
  • Meta 走的是把一个大改动拆成一串小改动、一层叠一层分别送审的路子,并把配套工具开源了出来。
  • 公开的代码托管平台后来上线的「叠放式合并请求」预览功能,是把大厂内部这套做法反向搬回了公开工具——一个内部做法能反流回公开产品,本身就说明它还是主线,不是过时的老规矩。

所以当有人说「这是大厂那一套,我们用不上」时,准确的说法是反过来的:正因为它在最复杂的场景里被反复验证过,它的默认形态才被削得很轻——轻到两个人的团队也能用。这一条下面第四节会给数字。

二、它的本体是知识传递,不是抓 bug

这是全页最该记住的一句。

Google 公开发表过一份针对自家代码审查的实证研究(《Modern Code Review: A Case Study at Google》,ICSE-SEIP),样本是约九百万次改动。结论出乎很多人意料:

当初引入这套流程的首要原因,是让代码更容易被读懂、更容易被维护。抓错是副产品,不是目的。

原始表述更直白——「逼开发者写出别人看得懂的东西」,以及那句被反复引用的:

代码必须充当未来开发者的老师。

这句话值得停一下。它说的不是「代码要写注释」,而是:这份东西本身要能教会下一个接手的人。而「有人会看、看不懂会问」这个机制,是唯一能持续逼出这个结果的东西——没有人看的时候,谁都会写得只有自己看得懂。

那它跟「走个形式」的区别在哪?

区别在产物。走形式的产物是一句口头的「行,你合吧」;这套流程的产物是一段带存档、挂在这次改动旁边、半年后还能翻出来的书面判断。前者随人走,后者留在东西上。

而这正是我们做这一整套内容的原因:用可以留存的介质传递思维,替代靠人在场传递思维。「代码要充当未来开发者的老师」和这句话,说的是同一件事。

三、先说难听的:这是投资,回报滞后

这一节放在前面,不是为了铺垫,是为了在你抱怨之前先把话说了

你会觉得烦,是真的,而且是预期之内的。

因为这套流程最大的两个收益,当期一个都不兑现

  • 第三个人加入的时候——他能靠翻历史看懂前因后果,而不是拉着你问三天。
  • 半年后回头查的时候——你能查到「当时为什么这么改」,而不是对着一堆自己写的东西发呆。

这两件事,今天都不会发生。今天发生的只有:你要多等一会儿。

这里有个很实际的东西要交给你:同一份体验,归因不同,结局相反。

  • 没人提前说过 → 你第三天的念头是「这套东西不好用」→ 放弃,并且从此认为方法有问题。
  • 提前说过 → 你第三天的念头是「我还在投资期」→ 撑过去,然后在第三个人进来那天拿到回报。

而归因方式是在第一天被设定的,不是在你烦的那一刻。 所以这一节必须放在这儿。

四、它本来就是轻的,重是因为用错了

「大厂那套太重」是最常见的一个误解。看一眼那份研究里的真实形态(同一份样本,数字不做改写):

实际值
一次改动的行数中位数 24 行
只改一个文件的改动超过 35%
只改一行的改动超过 10%
一次改动的审阅人数中位数 1 人
从提出到走完的耗时中位数不到 4 小时

也就是说,它的默认形态是:小、快、一个人看

那什么时候会变重?

攒大了的时候。一次塞进去几百行、跨好几块地方,审的人得先花半天搞懂你在干嘛——于是拖,于是堵,于是有人开始绕过它。

而流程一旦被绕过一次,就会被绕过第二次。这是这套东西真正的失效路径——不是它太重,是它被攒重了,然后被放弃了。

五、九个环节,每一环在买什么

前面讲的是「为什么值得」。这一节把它落到地上:每一环技术上在干什么、通俗怎么说,以及——最容易讲错的地方在哪。

第三列是这张表的重点。这九处误解,是我们在真实带教里一次次撞出来的,不是想出来的。

通俗说⚠️ 最容易讲错
① 建分支不是复印项目,是在时间线上放个书签,从这里另起一条支线以为建分支=复制整个项目,因而「不敢建」。实际上系统只记差异,建分支近乎零成本
② 改文件+提交保存是给自己看的;提交是给别人、和给半年后的自己看的把提交等同于「保存」。区别在于它强制你写一句「为什么」——「代码要充当未来开发者的老师」第一次落地就在这一格
③ 推送提交之前,东西只在你自己机器上;推送之后别人才看得见以为提交完别人就看到了。这套系统默认是离线的、本地的,这是它和云端文档最大的区别。(在网页上操作时,提交与推送合并成一个动作)
④ 开合并请求不是交东西,是交申请——东西在推送那步就已经上传了把它说成「上传代码」。合并请求里没有任何新内容,它只是一个请求加一个讨论区。★ 请求描述那一格,就是写给未来读者的那封信
⑤ 自动检查跑起来找一台完全不认识你的机器,从零把你的东西装一遍⚠️ 最贵的一条误解:以为检查通过=功能正确。自动检查通常只验「装不装得起来」,完全不验业务对不对。把文案改成一句废话它通过,改成一串乱码它照样通过检查挡的是「跑不起来」,不是「做错了」;做错了靠人看挡。
⑥ 审阅不是查错别字,是问「这件事该不该这么做」说成「检查有没有 bug」。九百万次改动得出的结论是:首要目的是可理解性与知识传递,抓错是副产品
⑦ 合并申请批准,改动进入主线⚠️ 合并 ≠ 上线。点完合并主干确实变了,但打开线上还是老样子——正在跑的是之前构建出来的成品,它不会自己去拉新的。(这个词在概念词典里有词条,点过去看
⑧ 部署把仓库里的图纸,变成服务器上真在跑的东西以为部署会自动发生。它通常是要人去做的。另外,不同形态的应用部署方式不同——有的构建完就生效、没有中断;有的必须重启进程,会有一小段停机
⑨ 看线上验收落在人眼睛看得见的地方拿「构建日志成功」或「接口返回正常」当验收。★ 验接口不等于验产品——接口全绿而页面什么都没渲染出来,是真实发生过的事。验收判据必须落在界面上的一个动作。

给刚上手的人一条实际建议

改动只涉及一个文件的小改时,在网页上直接操作比拉到本地更好——每一环在界面上都是一个独立按钮,形状最清楚。拉到本地的四个真正价值(本地跑起来、批量改、断网也能改、用本地工具),这时候一个都用不上。

两遍法:第一遍在网页上学形状;第二遍拉到本地,补上「本地副本」这一环。第一遍合并之后,你本地那份必然是落后的——第二遍开工前必须先拉一次。 这个落后是故意留给你的:在真实的别扭里学会它,比被口头告知一遍记得牢。

六、闸,还是自觉

到这里,「为什么值得」讲完了。但还剩最后一个问题,而它比前面所有问题都重要:

这些规矩,是靠人自觉执行,还是靠机器强制执行?

没有闸的时候,系统对下面这些动作一律不拦:跳过合并请求直接推主干(不拦)/该批的人没批、自己点了合并(不拦)/自动检查亮着红叉、照样能合并(不拦)/改了别人负责的地方、没有人被通知(不拦)。

在这种状态下流程跑通了,证明的是「这个人很自觉」。它没有证明:他赶时间的时候、或者第三个人加进来之后,这套东西还立不立得住。

有闸的时候:直接推主干会被拒绝/没批准时合并按钮点不动/检查没过时合并按钮点不动/碰到别人负责的地方会自动把他加成必须审阅的人。

在这种状态下跑通,证明的才是「流程能兜住人」——想图快也做不到

「人守规矩」和「规矩守人」是两回事:前者随人变,后者不随人变。

还有第三种状态,而它是最危险的那种

前面两种是教科书上的分法。下面这一种,是我们自己撞出来的。

我们给主干装了闸:自动检查被设成「必须通过才能合并」,分支保护也开着。设置页上,规则一条条列在那儿。

后来一位同事以「先复制一份仓库到自己名下,再从那份提合并请求」的方式参与协作——这是给权限较窄的协作者用的标准路子。她提的请求页面上,「等待检查结果」的字样也在。

看起来一切正常。

实际上:托管平台还有一个单独的开关,管的是「允不允许为这种从外部副本发起的请求运行自动检查」。那个开关,在组织层和仓库层,双双没开

结果是:从这条协作路径建立那天起,那道自动检查一次都没有为她跑过。整道闸,从来没有生效过。

它比「根本没装闸」更危险,因为屏幕上看不出区别。 没装闸的时候,人知道自己在裸奔;这种状态下,人以为自己被保护着。

它为什么很久都没被发现

这一段值得完整看一遍,因为每一步单独看都是对的:

  1. 刚建起这条协作路径时,那次请求是纯文档改动,按当时的配置,自动检查本就不该跑——零检查是预期之内的,没人起疑。
  2. 后来有一轮去掉了「文档改动跳过检查」的配置——但那一轮修的是另一个洞
  3. 再后来有一轮专门验证「纯文档改动也会触发检查」,用的是主仓自己的分支发起的请求——绿是真绿,但它绕开了「外部副本」这条路

三轮各自都对。合起来,恰好没有一轮踩到「外部副本 + 触发」这个组合。

于是有了两条我们此后写死的规矩:

一、一道闸能不能拦住人,等于「规则 × 触发 × 没有例外」三者相乘——任何一个是零,整道闸就是零。而它坏掉的时候,长得跟正常一模一样。

二、验一道闸,必须沿着它真正要拦的那条路走一遍:谁的账号、哪一种请求、哪一个动作触发。任何替代路径上的绿,只能证明替代路径。

再补一条,因为它当时让我们绕了两次弯:像「等待检查结果」这种卡住不动的状态,成因至少有四层——请求本身的、流程配置文件的、仓库设置的、组织策略的。这四层在页面上长得一模一样。 所以看到一个开关是灰的,第一反应不该是「怎么点亮它」,而是「谁把它锁住了」。

这件事对「值不值」意味着什么

回到第三节那句「这是投资,回报滞后」。第三种状态补上了它的另一半:

不只是回报会滞后——你甚至可能连投资都没真正发生。

一个团队完全可能装了一整套流程、开了所有该开的选项、每次合并都看到「等待检查」四个字,而那道闸从第一天起就没有通电。

「我们有流程」和「流程在生效」是两件事,中间隔着一次真实路径上的验证。

最后一句诚实话:这一套确实有代价。两个人的团队会觉得仪式重;收益兑现得慢;而且你必须提前约定一条紧急通道——线上真出事的时候直接修,事后补上记录,并且明确它是例外、不是常态。只讲好处不讲代价,你第一次等审批的时候就会觉得被忽悠了。

七、下一步

想自己往下学

(这一页讲的是「为什么」,下面几页讲「怎么做」)

想找我们一起做

这套形状不是代码专有的。你手上只要有「多个人在维护、会持续改、改错了有后果」的东西——话术库、提示词与 AI 配置、报价与参数表、作业流程文件、知识库文章——它都能套上去。每一环都可以整列替换:隔离可以是分支,也可以是一份草稿副本;申请可以是合并请求,也可以是一条走审批的提交;自动检查可以是构建,也可以是格式与禁用词扫描;审阅可以是逐行评论,也可以是一份审阅意见(但必须留下字,不能只点一个同意)。

认得出左边那一列,你换任何工具都能自己搭起来;绑死在某个工具上,工具一换就得重来。

如果你想看看这套形状放到你们的场景里该长什么样,。规模很小、东西很简单的时候,它可以退化成「一份共享文档开建议模式 + 一个人审」——形状不变,工具降级