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-{new,bad}=<term> --term-{old,good}=<term>] [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...] git bisect (bad|new|<term-new>) [<rev>] git bisect (good|old|<term-old>) [<rev>...] git bisect terms [--term-good | --term-bad] git bisect skip [(<rev>|<range>)...] git bisect reset [<commit>] git bisect (visualize|view) 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.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/view
To see the currently remaining suspects in gitk, issue the following command during the bisection process (the subcommand view can be used as an alternative to visualize):$ git bisect visualize
$ git bisect visualize --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.$ 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.
--first-parent
Follow only the first parent commit upon
seeing a merge commit.
In detecting regressions introduced through the merging of a branch, the merge
commit will be identified as introduction of the bug and its ancestors will be
ignored.
This option is particularly useful in avoiding false positives when a merged
branch contained broken or non-buildable commits, but the merge itself was
OK.
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 --no-ff 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
file:///usr/share/doc/git/html/git-bisect-lk2009.html
02/28/2023 | Git 2.39.2 |