提交列表与版本差异使用场景说明

本文介绍合并请求中提交列表与版本差异分别适用的场景和代表的意义。

查看提交列表和版本差异

云效合并请求的提交改动页面,提供了提交列表版本差异两个视图,为评审人提供全面的视角去了解代码改动过程:

1-3.png

下文具体介绍两个视图代表的意义。

通过 “提交列表” 快速了解最新改动,进行全量评审

提交历史是阅读和追溯代码改动的方式之一。假设在实现某个特性 feature-x 时计划的提交步骤如下:

commit-4: Implementation & Test cases 提交 //针对feature进行实现,并添加对应测试用例
   |
commit-3: Refactor-B 提交 //发现需要进行简单重构,优化 function-f 实现逻辑
   |
commit-2: Refactor-A 提交 //发现需要进行简单重构,抽取公共方法便于复用
   |
commit-1: Cleanup 提交 //发现我们要改动的文件,存在格式化问题,将文件进行格式化

针对以上实现路径对代码进行了对应的设计和实现,可以通过 git log adf3e902..HEAD 命令在终端查看提交历史:

commit 47c53b7ae262fe5a40906884ae9c0c993035c085 (HEAD -> feature-x)
Author: tenglong.tl <tenglong***@email.com>
Date:   Tue Sep 26 09:56:47 2023 +0800

    feat: implement feature-x and related test cases
    
    Signed-off-by: tenglong.tl <tenglong***@emailc.com>

commit 0b5c42b2bf252069931f724a74f2f0301e7dd8a3
Author: tenglong.tl <tenglong***@email.com>
Date:   Mon Sep 25 19:46:09 2023 +0800

    refactor: optimize f() to be shorter and simpler
    
    Signed-off-by: tenglong.tl <tenglong***@email.com>

commit 4f80f46afb585497ef3f6e0ecdafde1c4d11c273
Author: tenglong.tl <tenglong***@email.com>
Date:   Mon Sep 25 19:40:57 2023 +0800

    refactor: extract common func to reuse in future
    
    Signed-off-by: tenglong.tl <tenglong***@email.com>

commit f613e9882a4cb91f87dff215b2d08b94139b40b2
Author: tenglong.tl <tenglong***@email.com>
Date:   Mon Sep 25 19:37:43 2023 +0800

    cleanup: fixup the format alerts in x.java
    
    Signed-off-by: tenglong.tl <tenglong***@email.com>

以上git log代表为了开发这个特性对应的源码组织形式,叫做提交列表。 在 git log 后附带参数值adf3e902..HEAD,是为了过滤base之前的提交,仅仅查看新增的部分(在 Git 中称为一种notation"<commit1>..<commit2>"^<commit1> <commit2>" 的简写,即 "<commit1>"之前的提交都不展示,显示至 "<commit2>"为止的提交)。

优秀的提交列表可以清晰地体现开发者对于整个特性研发的设计思考过程,更进一步通过原子化的提交,让评审人高效地了解特性实现路径并可以逐个针对提交进行评审。原子化也可以帮助开发者解耦工程,可以针对单个提交进行独立修改(延展阅读:如何做好提交,成为有品位的工程师?),而不破坏其他的提交内容。

建议评审者应先关注提交列表而非直接查看文件改动。对提交本身的评审也非常重要,这是代码评审所推荐的一种优秀实践。即使不在代码评审场景,使用git log查看感兴趣的提交历史,了解开发者编程思路,也是使用频率最高的 Git 命令之一了。

提交列表尤其适用评审人首次进行全量评审的场景,这时评审人一般优先关注最新版本的代码改动,先总览一下当前最新版本的提交列表,往往可以让评审工作事半功倍:

1-3.png

通过 “版本差异” 定位版本(Patchset)之间提交变化,进行增量评审

提交列表可以满足首次评审时,查看最新代码改动的场景。但是,好的代码是不断迭代的,对应代码评审的版本(Patchset)也会不断更新,两个版本(Patchset)之间的提交改动可能很小,也可能因为一些原因导致新老变化大相径庭。

关注版本间提交的变化,可以轻松识别已经评审过的文件内容,而仅关注新变化的内容,进行增量评审,降低评审人力投入。

以上文的场景为例,评审作者创建一个评审的版本-1(Patchset-1)

47c53b7 (HEAD -> feature-x) feat: implement feature-x and related test cases
0b5c42b refactor: optimize f() to be shorter and simpler
4f80f46 refactor: extract common func to reuse in future
f613e98 cleanup: fixup the format alerts in x.java

版本-1(Patchset-1)中包含了 4 个提交,随后评审者-A针对提交feat: implement feature-x and related test cases给了评审意见:“该提交内容较多,原子化程度不高,建议拆分,从而更好的使用 git-bisect 命令进行提交的CI覆盖,方便后续评审和修改。”

于是作者更新代码,提交了评审版本-2(Patchset-2),保持其他三个提交不变,同时将提交 1 feat: implement feature-x and related test cases拆分为 4 个新提交:

此时,执行git log adf3e90..HEAD --oneline命令显示最新的提交列表变成如下形式:

3add20b controller: REST mapping and ACL implementation
7525c08 service: feat-X implementations and test cases
06a5e4f dao: implements DAO interface
054ea6d api: REST interface declaration
0b5c42b refactor: optimize f() to be shorter and simpler
4f80f46 refactor: extract common func to reuse in future
f613e98 cleanup: fixup the format alerts in x.java

评审版本-2(Patchset-2)评审版本-1(Patchset-1)提交列表进行对比,可以看到:

  • f613e98 4f80f46 0b5c42b3个提交保持不变。

  • 删除了提交47c53b7

  • 新增了 054ea6d 06a5e4f 7525c08 3add20b4 个提交。

对于评审者-A来说,保持不变的 3 个提交已经在评审版本-1(Patchset-1)中完成过评审,没必要再看一遍。仅需针对删除提交和新产生的 4 个提交进行再次评审。

这种评审的实践,对于评审效率的提升无疑是巨大的。一方面,评审者关注的改动范围得到的缩小,而不用每次都通过浏览全量的文件改动来识别差异另一方面,可以更加了解评审作者的编码思路和设计,帮助评审人给出更加正确和准确的评审建议。

识别提交变化,仅通过提交列表比较困难例如对于中间提交进行修改,重新优化提交说明,或是编排提交列表顺序。要想识别出这些改动,需要借助于 range-diff 命令,即通过git range-diff adf3e90..47c53b7 adf3e90..3add20b来查看版本范围(提交列表)之间的差异,提交改动在终端的展示如下:

image.png

其中:

  • =代表提交未变化。

  • <代表提交删除。

  • >代表提交新增。

  • !代表提交发生变化(例如:元数据例如提交说明、作者信息等,或者文件改动)。

对应在云效代码评审中,也可以通过版本差异视图在页面直接查看 range-diff 的内容:

1-3.png

总结

提交列表更适用于首次评审场景,对所有提交进行全量评审。而版本差异适合多次补丁迭代评审的场景,可以帮助评审者有效控制评审范围,其更加关注版本PatchSet的变化,进行增量评审

当把提交的内容尽量解耦,同时让每个提交具备原子性之后,频繁发送最新的版本补丁(基于补丁(patchset)的评审工作流)就变成了极为优秀的实践方式。一方面,可以及时的告知评审者们工作的进展,另一方面评审者每次评审的内容也可以基于递进式的方式,变得更加可控和高效。

假设如果在周五下班前一口气发送了包含上文示例中的4个提交补丁 A,结果却在代码评审时被告知 API 接口的设计存在问题,那么最坏的情况下需要修改 1~4 的全部4个提交,可是明明在周一的时候就完成了 API 接口的设计。最后,对于评审作者,优秀的提交也能更加及时地获取各方评审者的反馈,让问题得到提前修正的机会,形成低成本的正向评审循环。

云效代码评审秉承推广优秀实践的原则,在产品能力上支撑“小步快跑”的评审模式,期望帮助开发者简化繁重的代码评审工作,实现高效协同。