首页/开发/代码质量与评审速查/小 CL 原则:一次评审一个自包含改动
代码评审64 条

小 CL 原则:一次评审一个自包含改动

Google 评审文档建议把 CL 控制在小规模(约 100 行为参考),每个 CL 是单一自包含改动,便于评审、合并与回滚。

小 CL 原则是什么

Google 评审文档建议把一次改动控制在较小规模(文档给出的参考值约 100 行),并保持单一自包含:能独立理解、独立评审、独立回滚。小不是目的,目的是让评审者一次只需建模一件事,缺陷更容易被发现。文档同时强调:拆分的前提是每个 CL 本身仍然完整、可以独立合入。

基本信息

参考规模约 100 行(文档参考值,按语言与场景调整)
形态要求单一主题、自包含、可独立理解与回滚
例外情况全库机械改动可放宽行数,但必须机械且可验证
配套动作重构与功能分开提交,拆出的每一步都能通过 CI

为什么小 CL 更好

  • 评审更认真:一次看一百行与一次看两千行,注意力投放完全不同。
  • 缺陷更早暴露:改动小,问题边界清晰,容易复现与定位。
  • 合并更快:与主干冲突面小,被别人的改动打断的概率低。
  • 回滚半径小:线上出问题只退一个主题,不必连坐无关改动。
  • 二分定位方便:历史提交粒度细,问题引入点容易找。

小改动与大改动对比

维度小 CL大 CL
评审质量逐行细看,愿意提问题只扫结构,细节被跳过
合并冲突冲突少,重基准成本低挂几天就与主干严重冲突
回滚影响只退一个主题退回连带的无关改动
排障成本提交粒度细,易二分改动混杂,定位困难

拆分前的自查

拆分前的自查
git diff --stat          # 先看规模:文件数与行数是否合理
git diff --name-only     # 按文件归类,判断能否自然分组
# 常见切法:
# 1) 纯格式化或改名:单独一个 CL
# 2) 结构调整(不改行为):一个 CL
# 3) 行为变化:一个 CL,并带上测试
# 4) 文档与变更日志:一个 CL

拆不动的常见原因

  • 改动本身是原子替换(如切换某个库的调用):可接受,但要在描述里说明为何不可拆。
  • 存在依赖顺序:按依赖自底向上拆,先接口后实现,每一步都能编译。
  • 为凑行数硬拆:拆出无法独立合入的半成品,反而拉长依赖链。
  • 无关小修顺手塞进来:多个主题纠缠,评审者要同时对多件事表态。
  • 改动量大但主题单一(如全库替换某个调用):可与评审者约定抽样看关键文件加全量规则核对,而不是硬拆。

评审者视角的应对

  • 改动确实过大:先与作者确认能否拆分,再提出要求,不要只丢一句「太大了」。
  • 无法拆分的原子改动:至少要求描述写清范围与验证方式,缩短阅读路径。
  • 读大 CL 的顺序:先读描述与文件清单,再重点看行为变化与测试,格式类快速跳过。
  • 大 CL 里的问题分主次:阻塞项明确列出,细节建议标 nit,避免主要问题被淹没。
  • 同一天反复收到更新推送:建议作者攒齐一轮评论再更新,减少重复阅读。
行数只是参考值:更实用的判断标准是「一个评审者能否在一次阅读里完全理解这个改动」。
大功能可按「接口与脚手架 → 实现与单测 → 接线与集成 → 清理旧实现与开关」的顺序提交,每一步都保持仓库可构建。
拆得过碎同样有害:每个 CL 都不完整时,作者要同时维护多个分支,交付速度反而变慢。

易错点

  • 拆得过碎:每个 CL 都不完整,依赖链拉长,作者在多个分支间反复切换。
  • 为控制行数把无关小修混进同一 CL:主题纠缠,评审与回滚都被牵连。
  • 把「小」当成硬指标:为凑行数拆出无法独立合入的半成品,中间态编译不过。
  • 大范围机械改动不做标注:全库格式化淹没真实改动,评审者索性放弃细看。
  • 拆分但不保证每步可合入:主干长时间不可用,拖累其他人开发。

数据来源与参考

  • Google Engineering Practices · Small CLs
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌