小 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 都不完整时,作者要同时维护多个分支,交付速度反而变慢。