Git 分支和 Perl

work,我们有许多开发者向一个大型 Git 仓库提交代码,并运行一个庞大的测试套件来检查软件是否正确构建和运行。不可避免地,开发者会提交破坏测试的代码,在特别繁忙的时刻,很难弄清楚“是谁破坏了构建”。

这时可以使用 Git 的 bisect 命令。我提供已知最早坏提交的 SHA 值(或“HEAD”),以及最后一个正常提交的 SHA 值。

$ git bisect start HEAD b507d1a
Bisecting: 41 revisions left to test after this (roughly 5 steps)

然后我设置它运行,使用失败的测试脚本

$ git bisect run t/foo.t

Git 会检出 HEADb507d1a 之间的提交,并运行 t/foo.t 来确定它是好的还是坏的。然后它会选择这些提交的子集,检出其中一个并再次运行测试。Git 会继续进行,将提交划分为组并测试它们,直到找到测试失败的最早提交。这有点像游戏。

HUD targeting fighter jet

最终它会输出

6717e8dd92ccc6b8f1a058799e895a716bbbb3fd is the first bad commit
commit 6717e8dd92ccc6b8f1a058799e895a716bbbb3fd
Author: Spider <spider@example.com>
Date:   Mon Jul 24 10:56:41 2017 -0700

    Add some feature

我知道该联系谁来解决破坏构建的问题,所以我可以退出 bisect 进程

$ git bisect reset

bisect 和退出值

bisect 运行时会特别处理某些退出值:125 表示代码无法测试,128 或更高会中止 bisect 进程。如果 Perl 抛出异常,它将以 255 退出(而不是 0 表示通过和 1 表示测试失败),完全中止 bisect。

bisect run failed:
exit code 141 from 't/foo.t' is < 0 or >= 128

为了解决这个问题,将 t/foo.t 的调用包装在一个 shell 脚本中,将测试脚本的返回值限制在 127 以内

#!/bin/sh
"$@"
rv=$?
if [ $rv -gt 127 ]; then
  exit 127
else
  exit $rv
fi

变量 "$@" 是传递给 shell 脚本的命令字符串,每个参数中的空格都保留,所以它实际上执行了传递给它的任何参数(与 $* 不同,它会将每个参数拆分并在执行之前添加空格)。就像在 Perl 中一样,$? 是最后运行命令的退出值,在这里我将其分配给 rv。然后脚本以 127 或 rv 的值退出。我将脚本保存为 cap-exit-value,并像这样使用它

$ git bisect start HEAD b507d1a
Bisecting: 41 revisions left to test after this (roughly 5 steps)
$ git bisect run ./cap-exit-value t/foo.t

现在当 Git 进行 bisect 时,如果测试失败或 Perl 抛出异常,它将被视为失败,bisect 可以继续。

感谢我的同事 Frew,他首先向我解释了这个问题和解决方案。如果您喜欢这样的文章,您可能会喜欢他的 博客


这篇文章最初发布在 PerlTricks.com 上。

标签

David Farrell

David 是一名专业程序员,他经常 推文博客 关于代码和编程艺术。

浏览他们的文章

反馈

这篇文章有什么问题吗?请通过在 GitHub 上打开问题或拉取请求来帮助我们。