正确使用Diff范围进行diff-cover增量覆盖率分析

2025-04-04T22:48:11+08:00 | 2分钟阅读 | 更新于 2025-04-04T22:48:11+08:00

bestzy
正确使用Diff范围进行diff-cover增量覆盖率分析

本文记录了我在使用diff-cover进行增量代码覆盖率分析时会遇到错误。

背景

在使用 diff-cover 进行增量代码覆盖率分析时,我最近遇到一个令人头疼的问题:diff_cover 报错

diff_cover.command_runner.CommandError: fatal: origin/master...HEAD: no merge base

在查阅 diff-cover 的 Issues 后,我发现使用 --diff-range-notation 选项可以解决该错误。

然而,这却引出了另一个更棘手的问题:增量覆盖率的计算结果变得极不准确。报告中经常会包含大量不属于当前 MR 的代码改动,导致覆盖率数值异常偏高。

经过排查,我最终定位到罪魁祸首是 Git diff 的范围符号选择不当。

问题现象

最初,为了解决 no merge base 的报错,我使用了 --diff-range-notation 选项,但随即发现增量覆盖率数据与实际情况严重不符,包含了不属于当前 Merge Request 的代码变更。

问题排查

为了探究这个问题,我开始关注 --diff-range-notation '..' 参数。这个参数用于指定 Git diff 命令所使用的范围表示法。为了验证我的猜测,我尝试手动执行 git diff 命令,查看它实际比较的范围。假设当前分支是 feature-branch,目标分支是 main,我执行了以下命令:

git diff main..feature-branch

结果发现,这个命令实际上比较的是 main 分支到 feature-branch 分支的所有提交差异。这意味着它不仅包含了 feature-branch 分支基于 main 分支创建之后的所有提交,甚至连 main 分支在 feature-branch 创建之后进行的更新也会被包含在差异中。这也就解释了为什么 diff-cover 报告中会包含不属于当前 MR 的代码改动。

问题的根源在于我对 Git diff 双点 (..) 和三点 (…) 含义的理解不足。

解决方案

直接将 --diff-range-notation 改为 ... 表面上可以解决问题,但可能会再次触发 origin/master...HEAD: no merge base 错误。为了避免这种情况,我采取了一种更稳健的方案:

  1. 判断是否存在共同祖先: 使用 git merge-base 命令判断两个分支是否存在共同祖先。
  2. 选择合适的范围表示法:
    1. 如果 git merge-base 命令返回非 0 错误(表示不存在共同祖先),则使用双点比较 (git diff A..B)。
    2. 否则,使用三点比较 (git diff A...B),避免误判。

Git diff 双点 (..) 与三点 (…) 的区别:

  • 双点 (..)git diff A..B 比较的是从 A 分支到 B 分支的所有提交差异。它包含了 B 中所有不在 A 中的提交,以及 A 中所有不在 B 中的提交。换句话说,它比较的是 A 分支和 B 分支的完整状态。
  • 三点 (…)git diff A...B 比较的是 B 分支相对于 A 和 B 的共同祖先的差异。它只包含 B 分支相对于它们共同祖先的改动。这非常适合用于比较特性分支和主分支的差异,因为它只包含特性分支独有的更改。

总结

在使用 diff-cover 进行增量代码覆盖率分析时,正确理解和使用 Git diff 的范围表示法至关重要。通过结合 git merge-base 命令动态选择双点或三点比较,可以避免覆盖率计算结果包含不属于当前 MR 的代码改动,从而获得更准确的增量覆盖率数据。

© 2025 Bestzy's Blog

🌱 Powered by Hugo with theme Dream.

About Me

👋 Hi, This is Zheng Yi.