假设我突然发现我的 Git 存储库出现了问题。但是我知道它在几次提交之前就可以工作,我只是不记得是哪个提交。而不是试图找到一个“好”的提交来做一个 git bisect,我想问 Git(可能使用 bash 脚本),最近的“好”提交是什么?
另一个不只是选择不久前的提交并将其作为好的提交的另一个原因是,在我的仓库中,有许多坏的和好的提交混合在一起。它不是线性的。
那么我该如何循环,从最近的提交开始并根据需要执行一个命令,如果不好则返回 1,如果好则返回 0?
假设我突然发现我的 Git 存储库出现了问题。但是我知道它在几次提交之前就可以工作,我只是不记得是哪个提交。而不是试图找到一个“好”的提交来做一个 git bisect,我想问 Git(可能使用 bash 脚本),最近的“好”提交是什么?
另一个不只是选择不久前的提交并将其作为好的提交的另一个原因是,在我的仓库中,有许多坏的和好的提交混合在一起。它不是线性的。
那么我该如何循环,从最近的提交开始并根据需要执行一个命令,如果不好则返回 1,如果好则返回 0?
while ! good-or-bad-test-command ; do
git checkout HEAD^
done
但是,如果损坏只是在某处的最后几个提交中,您可以手动执行此操作。
$ good-or-bad-test-command
# if it fails, then:
$ git checkout HEAD^ # pop to previous
$ good-or-bad-test-command # <-- recalled by hitting up arrow in bash
# still fails:
$ git checkout HEAD^ # <-- recalled with up arrow
$ good-or-bad-test-command # <-- recalled
...
多亏了历史回忆,它比敲出一个循环需要更少的击键。
git checkout
避免移动您的分支HEAD
,使您处于“分离状态”,您可以轻松地从中恢复git checkout <yourbranch>
。
[编辑,2017 年 3 月]
但是,问题是,你为什么还要git bisect
在这种情况下使用?你已经线性地搜索了错误的提交,回到了好的提交;无需对相同的信息进行另一次二进制搜索。
只需猜测一下即可找到一些仍然不错的提交并继续前进,这可能需要更少的步骤git bisect
。
如果你怀疑你最近破坏了某些东西,只需返回 16 次提交。或 32 或其他。返回到最后一个标记的版本。二进制搜索将在以下位置快速归零:
$ git bisect start
$ git bisect bad # HEAD known to bad; almost always the case
$ git checkout HEAD~8 # wild guess; almost certainly before breakage
$ good-or-bad-test-command # check: is it really good?
$ # if not, git checkout HEAD~8 # go back more, repeat test
$ git bisect good # bisect begins
如果我们有一个历史很长的 git,并且发现很久以前就坏了(以前未经测试的东西现在已经测试过),我们可以以指数方式向后探测以找到一个好的提交git checkout HEAD~16
:那么如果这不好,git checkout HEAD~32
; 然后git checkout HEAD~64
。
这是通过未知范围进行二进制搜索的一般策略。不要线性扫描以确定范围,因为这会使算法线性化。如果我们以指数方式扩展范围,我们会保持对数。