我怎样才能知道 git bisect 接下来会尝试什么提交?

发布于 2024-09-08 13:35:45 字数 214 浏览 4 评论 0原文

在某些情况下,在 git bisect 会话期间,测试特定提交需要很长时间(例如,因为我必须构建完整的发布包并将其部署在特别奇怪的机器上)。事实上,测试构建需要很长时间,以至于我想在不知道当前测试是否成功的情况下开始构建接下来的两次提交。这样,我可以通过测试当前版本并并行构建接下来的两个版本来加速平分。

有谁知道让 git bisect 显示接下来的两个修订的技巧,具体取决于当前提交是好还是坏?

In some cases during a git bisect session, testing a particular commit takes quite long (for instance, because I have to build a full release package and deploy it on a particularly strange machine). In fact, testing a build takes so long that I'd like to start building the next two commits already without knowing whether the current test succeeds or not. That way, I can speed up bisecting by testing the current version and build the next two versions in parallel.

Does anybody know a trick to make git bisect show the next two revisions, depending on whether the current commit is good or bad?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

习ぎ惯性依靠 2024-09-15 13:35:45

git bisect 在内部使用 git rev-list --bisect 来找出哪个版本是两个版本之间的中点。您可以自己使用它来基本上重新实现 git bisect 。应该没那么难。

git bisect uses git rev-list --bisect internally to find out, which revision is the midpoint between two revisions. You can use it by yourself to basically reimplement git bisect. It shouldn't be that hard.

与他有关 2024-09-15 13:35:45

git bisect 在内部使用 git rev-list --bisect 来找出哪个版本是两个版本之间的中点。

Git 2.30(2021 年第一季度)发生了变化:“git bisect start/next"(man)在一个很大的历史跨度中花费大量时间试图准确地找到中间点;当我们看到足够接近中间点的提交时,可以通过停止来优化这一点。

请参阅 提交 0afcea7(2020 年 11 月 12 日),作者:SZEDER Gábor (szeder)
(由 Junio C Hamano -- gitster -- 合并于 提交 2557c11,2020 年 11 月 25 日)

bisect:松开一半( ) 检查大量提交

签字人:SZEDER Gábor

'git bisect start ...< /code>'(man)以及后续的 'git bisect (好|坏)< /code>'(man)当好提交和坏提交之间的给定/剩余修订范围很大并且包含大量合并提交时,例如在 git.git

$ git rev-list --count v1.6.0..v2.28.0
44284
$时间 git bisect start v2.28.0 v1.6.0
平分:此后还有 22141 个修订需要测试(大约 15 个步骤)
[e197c21807dacadc8305250baa0b9228819189d4]unable_to_lock_die():从unable_to_lock_index_die()重命名函数  

真实0米15.472秒
用户0分15分220秒
系统0m0.255s  

大部分运行时间都花在do_find_bisection()上,我们尝试找到一个尽可能接近坏修订和好修订之间中间点的提交,即处于好坏范围内的可到达提交数量是该范围内提交总数的一半。
因此,我们计算该范围内每个提交在好坏范围内可到达的提交数量,这对于线性历史记录来说是快速且容易的,甚至在我的机器上,线性范围内超过 300k 的提交也能在大约 0.3 秒内处理。< br>
唉,处理合并提交并不简单,而且相当昂贵,因为使用的算法似乎是二次的,导致上面显示的运行时间很长。

有趣的是,看看额外的提交可以产生多大的差异:

$ git rev-list --count v1.6.0^..v2.28.0
44285
$时间 git bisect start v2.28.0 v1.6.0^
平分:此后还有 22142 个修订需要测试(大约 15 个步骤)
[565301e41670825ceedf75220f2918ae76831240] 与 2.1.2 同步  

真实0米5.848秒
用户0m5.600s
系统0m0.252s  

差异是由尝试减少 1c4fea3a40< 中添加的运行时的优化之一引起的/a> ("git-rev-list --bisect: 优化", 2007-03-21, Git v1.5.2-rc0 -- 合并):

另一个小的优化是每当我们发现中途提交时
(即一次提交可以恰好达到一半的提交),
我们停止计算剩余的提交,因为我们找不到
任何比我们刚刚发现的更好的承诺。  

在第二个'git bisect start< /code>'(man)命令我们恰好在中间点找到了一个提交,并且可以提前返回,但是在第一种情况下,没有这样的提交,因此我们无法提前返回并最终计算好中所有提交中可到达的提交的数量- 射程不佳。

但是,当我们有数千个提交时,找到精确中间点并不那么重要,或多或少的一些提交不会对二等分产生任何真正的影响。

因此,让我们放宽 halfway() 帮助程序中的检查,将精确中点的 0.1% 以内的提交也视为一半,并将该函数重命名为 approx_halfway()< /code> 相应地。
这将使我们能够尽早返回更大的好坏范围,即使在中间点没有提交,从而大大减少上面第一个命令的运行时间,从大约 15 秒减少到 4.901 秒。

此外,即使恰好在中间点有提交,我们仍然可能在找到确切的中间点之前偶然发现 0.1% 范围内的提交,从而允许我们提前返回一点,从而稍微减少了运行时间第二条命令从 5.848s 到 5.058s。

请注意,此更改不会影响包含约 2000 次提交或更少的好坏范围,因为由于整数运算,0.1% 的容差变为零;但是,如果范围那么小,那么计算所有提交的可到达提交已经足够快了。

当然,这可能会改变在每个二分步骤中选择哪些提交,反过来,可能会改变找到第一个错误提交所需的二分步骤数。
如果必要的二分步骤的数量经常增加,那么这种更改可能会适得其反,因为每个步骤的构建和测试可能需要比节省的时间长得多的时间。
OTOH,如果步数减少,那就是双赢。

因此,我进行了一些测试,看看这种情况发生的频率:在 git.git,并使用 'git bisect git merge-base run --is-ancestor HEAD $first_bad_commit'(男人) 检查必要的二分步数。
在使用和不使用此补丁的情况下重复这一切 1000 次后,我发现:

  • 146 例比之前多了一步,149 例少了一步,其余 705 例步数不变。
    因此,二分步数确实在不可忽略的情况下发生了变化,但从长远来看,平均步数似乎并没有改变。
  • 第一个 'git bisect start'(man)命令在 456 个案例中速度提高了 3 倍以上,因此这种“在确切的中间点没有提交”的情况似乎很常见,值得关注。


git bisect uses git rev-list --bisect internally to find out, which revision is the midpoint between two revisions.

That has changed with Git 2.30 (Q1 2021): "git bisect start/next"(man) in a large span of history spends a lot of time trying to come up with exactly the half-way point; this can be optimized by stopping when we see a commit that is close enough to the half-way point.

See commit 0afcea7 (12 Nov 2020) by SZEDER Gábor (szeder).
(Merged by Junio C Hamano -- gitster -- in commit 2557c11, 25 Nov 2020)

bisect: loosen halfway() check for a large number of commits

Signed-off-by: SZEDER Gábor

'git bisect start ...'(man) and subsequent 'git bisect (good|bad)'(man) commands can take quite a while when the given/remaining revision range between good and bad commits is big and contains a lot of merge commits, e.g. in git.git:

$ git rev-list --count v1.6.0..v2.28.0
44284
$ time git bisect start v2.28.0 v1.6.0
Bisecting: 22141 revisions left to test after this (roughly 15 steps)
[e197c21807dacadc8305250baa0b9228819189d4] unable_to_lock_die(): rename function from unable_to_lock_index_die()  

real    0m15.472s
user    0m15.220s
sys     0m0.255s  

The majority of the runtime is spent in do_find_bisection(), where we try to find a commit as close as possible to the halfway point between the bad and good revisions, i.e. a commit from which the number of reachable commits that are in the good-bad range is half the total number of commits in that range.
So we count how many commits are reachable in the good-bad range for each commit in that range, which is quick and easy for a linear history, even over 300k commits in a linear range are handled in ~0.3s on my machine.
Alas, handling merge commits is non-trivial and quite expensive as the algorithm used seems to be quadratic, causing the long runtime shown above.

Interestingly, look at what a big difference one additional commit can make:

$ git rev-list --count v1.6.0^..v2.28.0
44285
$ time git bisect start v2.28.0 v1.6.0^
Bisecting: 22142 revisions left to test after this (roughly 15 steps)
[565301e41670825ceedf75220f2918ae76831240] Sync with 2.1.2  

real  0m5.848s
user  0m5.600s
sys   0m0.252s  

The difference is caused by one of the optimizations attempting to cut down the runtime added in 1c4fea3a40 ("git-rev-list --bisect: optimization", 2007-03-21, Git v1.5.2-rc0 -- merge):

Another small optimization is whenever we find a half-way commit
(that is, a commit that can reach exactly half of the commits),
we stop giving counts to remaining commits, as we will not find
any better commit than we just found.  

In this second 'git bisect start'(man) command we happen to find a commit exactly at the halfway point and can return early, but in the first case there is no such commit, so we can't return early and end up counting the number of reachable commits from all commits in the good-bad range.

However, when we have thousands of commits it's not all that important to find the exact halfway point, a few commits more or less doesn't make any real difference for the bisection.

So let's loosen the check in the halfway() helper to consider commits within about 0.1% of the exact halfway point as halfway as well, and rename the function to approx_halfway() accordingly.
This will allow us to return early on a bigger good-bad range, even when there is no commit exactly at the halfway point, thereby reducing the runtime of the first command above considerably, from ~15s to 4.901s.

Furthermore, even if there is a commit exactly at the halfway point, we might still stumble upon a commit within that 0.1% range before finding the exact halfway point, allowing us to return a bit earlier, slightly reducing the runtime of the second command from 5.848s to 5.058s.

Note that this change doesn't affect good-bad ranges containing ~2000 commits or less, because that 0.1% tolerance becomes zero due to integer arithmetic; however, if the range is that small then counting the reachable commits for all commits is already fast enough anyway.

Naturally, this will likely change which commits get picked at each bisection step, and, in turn, might change how many bisection steps are necessary to find the first bad commit.
If the number of necessary bisection steps were to increase often, then this change could backfire, because building and testing at each step might take much longer than the time spared.
OTOH, if the number of steps were to decrease, then it would be a double win.

So I ran some tests to see how often that happens: picked random good and bad starting revisions at least 50k commits apart and a random first bad commit in between in git.git, and used 'git bisect git merge-base run --is-ancestor HEAD $first_bad_commit'(man) to check the number of necessary bisection steps.
After repeating all this 1000 times both with and without this patch I found that:

  • 146 cases needed one more bisection step than before, 149 cases needed one less step, while in the remaining 705 cases the number of steps didn't change.
    So the number of bisection steps does indeed change in a non-negligible number of cases, but it seems that the average number of steps doesn't change in the long run.
  • The first 'git bisect start'(man) command got over 3x faster in 456 cases, so this "no commit at the exact halfway point" case seems to be common enough to care about.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文