【问题标题】:How can I find out what commit(s) git bisect would try next?我怎样才能找出 git bisect 下一步会尝试什么提交?
【发布时间】:2011-03-11 23:01:59
【问题描述】:

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

有人知道让git bisect 显示下两个修订版的技巧吗,这取决于当前提交的好坏?

【问题讨论】:

    标签: git debugging git-bisect


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      参见SZEDER Gábor (szeder)commit 0afcea7(2020 年 11 月 12 日)。
      (由 Junio C Hamano -- gitster -- 合并到 commit 2557c11,2020 年 11 月 25 日)

      bisect: 放松halfway() 检查大量提交

      签字人:SZEDER Gábor

      'git bisect start ...'(man) 和后续的 'git bisect (good|bad)'(man) 命令可能需要很长时间好的和坏的提交之间的修订范围很大并且包含很多合并提交,例如在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  
      

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

      有趣的是,看看一个额外的提交可以带来多大的不同:

      $ 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  
      

      差异是由于尝试减少 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.  
      

      在第二个 'git bisect start'(man) 命令中,我们恰好在中途发现了一个提交,并且可以提前返回,但在第一种情况下,没有这样的提交,所以我们不能提前返回并最终计算好坏范围内所有提交的可达提交数。

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

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

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

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

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

      所以我进行了一些测试,看看这种情况发生的频率:随机选择好的和坏的开始修订,至少有 50k 次提交,并在 git.git 之间随机选择第一个错误提交,并使用 'git bisect git merge-base run --is-ancestor HEAD $first_bad_commit' (man) 检查必要的二等分步数。
      在使用和不使用此补丁的情况下重复所有这 1000 次后,我发现:

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

      【讨论】:

        猜你喜欢
        • 2020-11-27
        • 2016-07-29
        • 1970-01-01
        • 2010-10-21
        • 2010-11-17
        • 2013-02-08
        • 2017-05-13
        • 2021-05-21
        • 2018-08-27
        相关资源
        最近更新 更多