如何使用git bisect查找第一个GOOD提交?


90

我有以下问题:

  • 该版本master工作正常
  • master(例如last)之前存在错误的最后一个标记的版本
  • 同事需要last针对该特定错误的补丁程序

好的。让我们向朋友询问git bisect修复该错误的修订:

git bisect start
git bisect bad last
git bisect good master

但这是行不通的:

一些好的转速不是坏转速的始祖。
git bisect在这种情况下无法正常工作。
也许您会误认为好转速和差转速?

有什么克服的建议吗?我是否错过了文档中的某些内容?


1
我正在运行git bisect run ...自动平分。因此,我没有机会只是交换单词goodbad(这太明显了)。如何使用run找到第一个好的修订版?
DanielBöhmer16年

@DanielBöhmer:您必须正在运行的脚本中交换术语,不是吗?
eckes

脚本由经营git bisect run回报好的的退出代码,而不是作为一个字符串。请参阅下面我刚刚发布的答案。
DanielBöhmer16年

@DanielBöhmer:好吧,在这种情况下,您必须将返回码取反,不是吗?
eckes

正确,这就是我的答案中描述的内容。
DanielBöhmer16年

Answers:


98

从git 2.7开始,您可以使用--term-old和--term-new参数。

例如,您可以这样确定一个解决问题的提交:

git bisect start --term-new=fixed --term-old=unfixed
git bisect fixed master
git bisect unfixed $some-old-sha1

在测试时,请说出git bisect fixedgit bisect unfixed适当说。

旧答案,对于2.7之前的git版本

与其暂时训练自己认为坏意味着好,好意味着坏,为什么不创建一些别名呢?

~/.gitconfig添加以下内容:

[alias]
        bisect-fixed = bisect bad
        bisect-unfixed = bisect good

您可以这样确定一个解决问题的提交:

$ git bisect start
$ git bisect-fixed master
$ git bisect-unfixed $some-old-sha1

在测试时,请说出git bisect-fixedgit bisect-unfixed适当说。


5
顺便说一句,git不允许您为子命令创建别名。因此破折号。如果确实可行(或可行),希望有人会更新答案。
Michael Wolf

3
即使您使用别名,git的输出也不会,因此它仍将报告foo is the first bad commit,因此似乎仍然需要进行临时培训,不是吗?
ThomasW

2
有道理。(支持您的评论。)尽管希望如此,但至少要减少一点额外的认知负担,而且作为程序员,我们已经有很多工作要做。
Michael Wolf

1
我建议使用别名“之前”和“之后”。这样,您就没有进行反转的认知开销:“当我看到错误时,我应该写'good'”;取而代之的是,您只有(可能较小)的开销,可以记住您正在寻找错误的出现/消失(即,记住要寻找的更改类型–“在做什么之前?”)。
JonasKölker'17 -10-16

1
@JonasKölker,这是个好主意。根据您的建议,我在答案中使用了建议的别名,以及bisect-after = bisect badbisect-before = bisect good。现在,我可以使用任何一组别名。我们将看到使用几次后最终会得到我更多的青睐。
加布里埃尔·斯台普斯

47

我只是“欺骗” git并交换好<=>坏的含义。

换句话说,将“不良”视为不会出现问题的东西,因此这不是修补程序所基于的“良好”版本。

好与坏都是相当主观的概念,对吗?:)

git bisect start
git bisect good last
git bisect bad master

2
好吧,如果您考虑这一点,就没有什么总的意义(好坏在宗教上)是好是坏。.这仅取决于您的目的。这样一来,它并不是真正的作弊-但也许是Git's Sin(继续关注宗教话题:D是选择这样一个有争议的术语,而不是更为中立的“目标” /“起源”。)但是,是的,哲学可以是介意的-令人难以置信的;-)
歌手

这肯定是我第一次听说错误可能是“好的”。
MarcH 2015年

1
这是我在发现这个问题之前所做的事情。我不再做了。请记住,在整个二分法出错之前,只需采取一个错误的答案即可。不要扭曲你的想法。
proski

20

如果您git bisect run像我一直在使用Perl的prove命令(运行自动测试)那样使用,则没有机会交换goodbad。测试成功将报告为退出代码。

我找到了一种有效的Bash语法来否定由以下程序运行的程序的退出代码git bisect run

git bisect start
git bisect bad HEAD                 # last revision known to PASS the tests
git bisect good $LAST_FAIL_REVISION # last revision known to FAIL the tests
git bisect run bash -c "! prove"

这使我第一次通过了由进行的测试的修订prove


我同意,我不想修改我的测试用例,所以这很完美。
seanlinsley

8

Git现在允许您使用oldnew而无需先定义它们。您必须在git bisect start没有提交的情况下调用作为进一步的参数,然后通过调用适当地开始二等分

git bisect old <rev>
git bisect new <rev>

https://git-scm.com/docs/git-bisect#_alternate_terms

这基本上就是@MarcH所建议的实现方式。


1
这是最相关的答案(对于现代git)。并且开始命令应该是(根据您共享的链接):git bisect start --term-new fixed --term-old broken
Sam Protsenko '18年

真正。这些选项何时引入?我想更新我的答案。
Michael Wolf

@MichaelWolf他们出现在版本2.7.0中
GKFX

6

Git的别名是一个好主意,但是术语fixedunfixed具有比相同的问题goodbad:你不能让他们同时兼容这两种回归和级数。容易找到两种方式起作用的单词很容易:只需从原始的二进制搜索术语中挑选出来,该术语本质上是中性的,无需事先了解好坏。例如:

git config --global alias.bisect-high 'bisect bad'
git config --global alias.bisect-low  'bisect good'

使用此类中立术语,您始终可以输入:(git bisect-highgit bisect-upper,或git-bisect max,...您的选择!)无论您要寻找回归还是修正

不幸的是,git bisect开发人员无法简单地重用任何现有条款。一般来说,用户界面不是git关心的问题:http : //stevebennett.me/2012/02/24/10-things-i-hate-about-git/


来自:git.github.io/rev_news/2015/07/08/edition-5 “正在完善一些补丁程序系列,以允许git bisect使用任意对术语代替好坏,...”
MarcH
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.