other versions
- jessie 1:2.1.4-2.1+deb8u6
- jessie-backports 1:2.11.0-3~bpo8+1
- stretch 1:2.11.0-3+deb9u4
- testing 1:2.20.1-2
- stretch-backports 1:2.20.1-1~bpo9+1
- unstable 1:2.20.1-2
- experimental 1:2.21.0+next.20190320-1
GIT-BISECT(1) | Git Manual | GIT-BISECT(1) |
NAME¶
git-bisect - Use binary search to find the commit that introduced a bugSYNOPSIS¶
git bisect <subcommand> <options>
DESCRIPTION¶
The command takes various subcommands, and different options depending on the subcommand:git bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>] [--no-checkout] [<bad> [<good>...]] [--] [<paths>...] git bisect (bad|new) [<rev>] git bisect (good|old) [<rev>...] git bisect terms [--term-good | --term-bad] git bisect skip [(<rev>|<range>)...] git bisect reset [<commit>] git bisect visualize git bisect replay <logfile> git bisect log git bisect run <cmd>... git bisect help
Basic bisect commands: start, bad, good¶
As an example, suppose you are trying to find the commit that broke a feature that was known to work in version v2.6.13-rc2 of your project. You start a bisect session as follows:$ git bisect start $ git bisect bad # Current version is bad $ git bisect good v2.6.13-rc2 # v2.6.13-rc2 is known to be good
Bisecting: 675 revisions left to test after this (roughly 10 steps)
$ git bisect good
$ git bisect bad
Bisecting: 337 revisions left to test after this (roughly 9 steps)
Bisect reset¶
After a bisect session, to clean up the bisection state and return to the original HEAD, issue the following command:$ git bisect reset
$ git bisect reset <commit>
Alternate terms¶
Sometimes you are not looking for the commit that introduced a breakage, but rather for a commit that caused a change between some other "old" state and "new" state. For example, you might be looking for the commit that introduced a particular fix. Or you might be looking for the first commit in which the source-code filenames were finally all converted to your company’s naming standard. Or whatever. In such cases it can be very confusing to use the terms "good" and "bad" to refer to "the state before the change" and "the state after the change". So instead, you can use the terms "old" and "new", respectively, in place of "good" and "bad". (But note that you cannot mix "good" and "bad" with "old" and "new" in a single session.) In this more general usage, you provide git bisect with a "new" commit has some property and an "old" commit that doesn’t have that property. Each time git bisect checks out a commit, you test if that commit has the property. If it does, mark the commit as "new"; otherwise, mark it as "old". When the bisection is done, git bisect will report which commit introduced the property. To use "old" and "new" instead of "good" and bad, you must run git bisect start without commits as argument and then run the following commands to add the commits:git bisect old [<rev>]
git bisect new [<rev>...]
git bisect terms
git bisect start --term-old <term-old> --term-new <term-new>
git bisect start --term-old fast --term-new slow
git bisect start --term-new fixed --term-old broken
Bisect visualize¶
To see the currently remaining suspects in gitk, issue the following command during the bisection process:$ git bisect visualize
$ git bisect view --stat
Bisect log and bisect replay¶
After having marked revisions as good or bad, issue the following command to show what has been done so far:$ git bisect log
$ git bisect reset $ git bisect replay that-file
Avoiding testing a commit¶
If, in the middle of a bisect session, you know that the suggested revision is not a good one to test (e.g. it fails to build and you know that the failure does not have anything to do with the bug you are chasing), you can manually select a nearby commit and test that one instead. For example:$ git bisect good/bad # previous round was good or bad. Bisecting: 337 revisions left to test after this (roughly 9 steps) $ git bisect visualize # oops, that is uninteresting. $ git reset --hard HEAD~3 # try 3 revisions before what # was suggested
Bisect skip¶
Instead of choosing a nearby commit by yourself, you can ask Git to do it for you by issuing the command:$ git bisect skip # Current version cannot be tested
$ git bisect skip v2.5..v2.6
$ git bisect skip v2.5 v2.5..v2.6
Cutting down bisection by giving more parameters to bisect start¶
You can further cut down the number of trials, if you know what part of the tree is involved in the problem you are tracking down, by specifying path parameters when issuing the bisect start command:$ git bisect start -- arch/i386 include/asm-i386
$ git bisect start v2.6.20-rc6 v2.6.20-rc4 v2.6.20-rc1 -- # v2.6.20-rc6 is bad # v2.6.20-rc4 and v2.6.20-rc1 are good
Bisect run¶
If you have a script that can tell if the current source code is good or bad, you can bisect by issuing the command:$ git bisect run my_script arguments
OPTIONS¶
--no-checkoutDo not checkout the new working tree at each iteration of
the bisection process. Instead just update a special reference named
BISECT_HEAD to make it point to the commit that should be tested.
This option may be useful when the test you would perform in each step does not
require a checked out tree.
If the repository is bare, --no-checkout is assumed.
EXAMPLES¶
•Automatically bisect a broken build between v1.2
and HEAD:
$ git bisect start HEAD v1.2 -- # HEAD is bad, v1.2 is good $ git bisect run make # "make" builds the app $ git bisect reset # quit the bisect session
•Automatically bisect a test failure between
origin and HEAD:
$ git bisect start HEAD origin -- # HEAD is bad, origin is good $ git bisect run make test # "make test" builds and tests $ git bisect reset # quit the bisect session
•Automatically bisect a broken test case:
Here we use a test.sh custom script. In this script, if make
fails, we skip the current commit. check_test_case.sh should exit
0 if the test case passes, and exit 1 otherwise.
It is safer if both test.sh and check_test_case.sh are outside the
repository to prevent interactions between the bisect, make and test processes
and the scripts.
$ cat ~/test.sh #!/bin/sh make || exit 125 # this skips broken builds ~/check_test_case.sh # does the test case pass? $ git bisect start HEAD HEAD~10 -- # culprit is among the last 10 $ git bisect run ~/test.sh $ git bisect reset # quit the bisect session
•Automatically bisect with temporary modifications
(hot-fix):
This applies modifications from a hot-fix branch before each test run, e.g. in
case your build or test environment changed so that older revisions may need a
fix which newer ones have already. (Make sure the hot-fix branch is based off
a commit which is contained in all revisions which you are bisecting, so that
the merge does not pull in too much, or use git cherry-pick instead of
git merge.)
$ cat ~/test.sh #!/bin/sh # tweak the working tree by merging the hot-fix branch # and then attempt a build if git merge --no-commit hot-fix && make then # run project specific test and report its status ~/check_test_case.sh status=$? else # tell the caller this is untestable status=125 fi # undo the tweak to allow clean flipping to the next commit git reset --hard # return control exit $status
•Automatically bisect a broken test case:
This shows that you can do without a run script if you write the test on a
single line.
$ git bisect start HEAD HEAD~10 -- # culprit is among the last 10 $ git bisect run sh -c "make || exit 125; ~/check_test_case.sh" $ git bisect reset # quit the bisect session
•Locate a good region of the object graph in a
damaged repository
In this case, when git bisect run finishes, bisect/bad will refer to a
commit that has at least one parent whose reachable graph is fully traversable
in the sense required by git pack objects.
$ git bisect start HEAD <known-good-commit> [ <boundary-commit> ... ] --no-checkout $ git bisect run sh -c ' GOOD=$(git for-each-ref "--format=%(objectname)" refs/bisect/good-*) && git rev-list --objects BISECT_HEAD --not $GOOD >tmp.$$ && git pack-objects --stdout >/dev/null <tmp.$$ rc=$? rm -f tmp.$$ test $rc = 0' $ git bisect reset # quit the bisect session
•Look for a fix instead of a regression in the
code
or:
$ git bisect start $ git bisect new HEAD # current commit is marked as new $ git bisect old HEAD~10 # the tenth commit from now is marked as old
$ git bisect start --term-old broken --term-new fixed $ git bisect fixed $ git bisect broken HEAD~10
Getting help¶
Use git bisect to get a short usage description, and git bisect help or git bisect -h to get a long usage description.SEE ALSO¶
Fighting regressions with git bisect[1], git-blame(1).GIT¶
Part of the git(1) suiteNOTES¶
- 1.
- Fighting regressions with git bisect
05/15/2017 | Git 2.11.0 |