如何使用git bisect:使用单元测试来确定错误提交?

时间:2012-10-06 14:00:20

标签: git unit-testing git-bisect

我是git的新手,刚刚发现了“git bisect”。当您使用新编写的单元测试(事先没有)检查错误时,通常如何使用?

假设我们有一个包含单元测试的存储库,但是 - 经常 - 它们并不完整。在某些版本中,我们发现某个功能无效,但我们知道它之前的某个版本。不幸的是,单元测试未检查该功能。我现在想做的是:

  1. 编写测试用例(当然首先失败)
  2. 使用此测试用例
  3. 查找使用git bisect引入错误的提交
  4. 更正错误并提交修复程序(和测试用例)
  5. 此用例有一个问题。由于git bisect检出旧版本,刚插入的测试用例不会出现,所以我不能用它来检查错误。我可以尝试不提交测试,但要将其保持为本地更改。但想象一下,在某些版本中,测试文件发生了变化,我可能会遇到合并冲突。

    那该怎么办?如何使用git bisect?

3 个答案:

答案 0 :(得分:10)

我通常使用bisect来识别何时引入错误,以便我可以查看单个提交以查找错误原因。当我知道某些东西曾经工作但现在却没有时,这很有用。我首先选择或找到一个有效的旧提交,用git bisect good标记,用git bisect bad标记头部,然后通过bisect直到git告诉我引入问题的提交。有时候我可以在开始这个过程之前编写单元测试,有时候在看到引入bug的代码之后我就无法编写它。

所以,假设我在进行git bisect过程时需要在每个点使用单元测试或其他一些代码或脚本。当我走的时候,藏匿对于持有它是有用的。所以,

git stash save blah
git bisect bad (and now I'm on a new commit)
git stash pop
mvn clean test

git stash save blah
git bisect good
git stash pop
mvn clean test

等等。

答案 1 :(得分:2)

首先,在尝试此操作之前,请确保您的git status是干净的 - 我建议使用可调用git reset --hard的脚本,因此任何未提交的更改都将丢失。

执行此操作的一种方法是首先将最近测试的源代码复制到某个位置,该位置从未在存储库的历史记录中(或存储库之外的某个位置)进行跟踪。然后编写一个脚本:

  1. 将最新的测试复制到源树中
  2. 运行测试,保存返回代码。
  3. git reset --hard是否会清除步骤1中的更改​​
  4. 使用从2保存的返回代码退出。
  5. 然后,在将两个提交标记为好与坏之后将git bisect提供给某个地方,您可以使用git bisect run YOUR-SCRIPT查找最近一次单元测试失败的第一次提交。

    此方法基本上是建议的in the documentation for git bisect run,其中包含:

      

    您可能经常发现在二等分会话期间您希望进行临时修改(例如,s / #define DEBUG 0 / #define DEBUG 1 /在头文件中,或者“没有此提交的修订版需要应用此修补程序解决另一个问题,这个二分法不是   感兴趣的“)适用于正在测试的修订版。

         

    为了应对这种情况,在内部git bisect找到要测试的下一个修订版之后,脚本可以在编译之前应用补丁,运行实际测试,然后决定是否通过了修订(可能带有所需的补丁)测试然后将树倒回到原始状态。最后,脚本应该以真实测试的状态退出,让“git bisect run”命令循环确定bisect会话的最终结果。

答案 2 :(得分:1)

你还没有提到你正在使用哪种技术,所以我将以Ruby为例,这是我最熟悉的。不过,同样的原则也适用于其他技术。

  1. 将项目目录中的最新测试文件放在之外。在这里,我假设它在/tmp/my_test.rb

  2. 在您的存储库中,创建一个小的shell脚本,比如test_runner.sh

    #!/usr/bin/env sh    
    cp -f /tmp/my_test.rb test/my_test.rb # This will potentially overwrite some old test file
    ruby test/my_test.rb # Change for whatever test runner you use
    test_result=$?
    git checkout test/my_test.rb # Undoes any changes that might have been made
    exit $test_result
    
  3. 标记提交为好/坏,通常用bisect完成。

  4. 使用git bisect run test_runner.sh并抓住一杯咖啡,而git会找到你的错误。