diff options
Diffstat (limited to 'Documentation/git-bisect.txt')
-rw-r--r-- | Documentation/git-bisect.txt | 242 |
1 files changed, 176 insertions, 66 deletions
diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index f986c5cb3a..7e79aaedeb 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -3,7 +3,7 @@ git-bisect(1) NAME ---- -git-bisect - Find by binary search the change that introduced a bug +git-bisect - Use binary search to find the commit that introduced a bug SYNOPSIS @@ -16,74 +16,89 @@ DESCRIPTION The command takes various subcommands, and different options depending on the subcommand: - git bisect help - git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<paths>...] - git bisect bad [<rev>] - git bisect good [<rev>...] + 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 -This command uses 'git rev-list --bisect' to help drive the -binary search process to find which change introduced a bug, given an -old "good" commit object name and a later "bad" commit object name. - -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. +This command uses a binary search algorithm to find which commit in +your project's history introduced a bug. You use it by first telling +it a "bad" commit that is known to contain the bug, and a "good" +commit that is known to be before the bug was introduced. Then `git +bisect` picks a commit between those two endpoints and asks you +whether the selected commit is "good" or "bad". It continues narrowing +down the range until it finds the exact commit that introduced the +change. + +In fact, `git bisect` can be used to find the commit that changed +*any* property of your project; e.g., the commit that fixed a bug, or +the commit that caused a benchmark's performance to improve. To +support this more general usage, the terms "old" and "new" can be used +in place of "good" and "bad", or you can choose your own terms. See +section "Alternate terms" below for more information. Basic bisect commands: start, bad, good ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Using the Linux kernel tree as an example, basic use of the bisect -command is as follows: +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 was the last version - # tested that was good +$ git bisect good v2.6.13-rc2 # v2.6.13-rc2 is known to be good +------------------------------------------------ + +Once you have specified at least one bad and one good commit, `git +bisect` selects a commit in the middle of that range of history, +checks it out, and outputs something similar to the following: + +------------------------------------------------ +Bisecting: 675 revisions left to test after this (roughly 10 steps) ------------------------------------------------ -When you have specified at least one bad and one good version, the -command bisects the revision tree and outputs something similar to -the following: +You should now compile the checked-out version and test it. If that +version works correctly, type ------------------------------------------------ -Bisecting: 675 revisions left to test after this +$ git bisect good ------------------------------------------------ -The state in the middle of the set of revisions is then checked out. -You would now compile that kernel and boot it. If the booted kernel -works correctly, you would then issue the following command: +If that version is broken, type ------------------------------------------------ -$ git bisect good # this one is good +$ git bisect bad ------------------------------------------------ -The output of this command would be something similar to the following: +Then `git bisect` will respond with something like ------------------------------------------------ -Bisecting: 337 revisions left to test after this +Bisecting: 337 revisions left to test after this (roughly 9 steps) ------------------------------------------------ -You keep repeating this process, compiling the tree, testing it, and -depending on whether it is good or bad issuing the command "git bisect good" -or "git bisect bad" to ask for the next bisection. +Keep repeating the process: compile the tree, test it, and depending +on whether it is good or bad run `git bisect good` or `git bisect bad` +to ask for the next commit that needs testing. + +Eventually there will be no more revisions left to inspect, and the +command will print out a description of the first bad commit. The +reference `refs/bisect/bad` will be left pointing at that commit. -Eventually there will be no more revisions left to bisect, and you -will have been left with the first bad kernel revision in "refs/bisect/bad". Bisect reset ~~~~~~~~~~~~ After a bisect session, to clean up the bisection state and return to -the original HEAD (i.e., to quit bisecting), issue the following command: +the original HEAD, issue the following command: ------------------------------------------------ $ git bisect reset @@ -100,9 +115,83 @@ instead: $ git bisect reset <commit> ------------------------------------------------ -For example, `git bisect reset HEAD` will leave you on the current -bisection commit and avoid switching commits at all, while `git bisect -reset bisect/bad` will check out the first bad revision. +For example, `git bisect reset bisect/bad` will check out the first +bad revision, while `git bisect reset HEAD` will leave you on the +current bisection commit and avoid switching commits at all. + + +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>] +------------------------------------------------ + +to indicate that a commit was before the sought change, or + +------------------------------------------------ +git bisect new [<rev>...] +------------------------------------------------ + +to indicate that it was after. + +To get a reminder of the currently used terms, use + +------------------------------------------------ +git bisect terms +------------------------------------------------ + +You can get just the old (respectively new) term with `git bisect term +--term-old` or `git bisect term --term-good`. + +If you would like to use your own terms instead of "bad"/"good" or +"new"/"old", you can choose any names you like (except existing bisect +subcommands like `reset`, `start`, ...) by starting the +bisection using + +------------------------------------------------ +git bisect start --term-old <term-old> --term-new <term-new> +------------------------------------------------ + +For example, if you are looking for a commit that introduced a +performance regression, you might use + +------------------------------------------------ +git bisect start --term-old fast --term-new slow +------------------------------------------------ + +Or if you are looking for the commit that fixed a bug, you might use + +------------------------------------------------ +git bisect start --term-new fixed --term-old broken +------------------------------------------------ + +Then, use `git bisect <term-old>` and `git bisect <term-new>` instead +of `git bisect good` and `git bisect bad` to mark commits. Bisect visualize ~~~~~~~~~~~~~~~~ @@ -117,7 +206,7 @@ $ git bisect visualize `view` may also be used as a synonym for `visualize`. If the 'DISPLAY' environment variable is not set, 'git log' is used -instead. You can also give command line options such as `-p` and +instead. You can also give command-line options such as `-p` and `--stat`. ------------ @@ -147,17 +236,17 @@ $ git bisect replay that-file Avoiding testing a commit ~~~~~~~~~~~~~~~~~~~~~~~~~ -If, in the middle of a bisect session, you know that the next suggested -revision is not a good one to test (e.g. the change the commit -introduces is known not to work in your environment and you know it -does not have anything to do with the bug you are chasing), you may -want to find a nearby commit and try that instead. +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 +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 @@ -167,20 +256,21 @@ Then compile and test the chosen revision, and afterwards mark the revision as good or bad in the usual manner. Bisect skip -~~~~~~~~~~~~ +~~~~~~~~~~~ -Instead of choosing by yourself a nearby commit, you can ask Git -to do it for you by issuing the command: +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 ------------ -But Git may eventually be unable to tell the first bad commit among -a bad commit and one or more skipped commits. +However, if you skip a commit adjacent to the one you are looking for, +Git will be unable to tell exactly which of those commits was the +first bad one. -You can even skip a range of commits, instead of just one commit, -using the "'<commit1>'..'<commit2>'" notation. For example: +You can also skip a range of commits, instead of just one commit, +using range notation. For example: ------------ $ git bisect skip v2.5..v2.6 @@ -196,8 +286,8 @@ would issue the command: $ git bisect skip v2.5 v2.5..v2.6 ------------ -This tells the bisect process that the commits between `v2.5` included -and `v2.6` included should be skipped. +This tells the bisect process that the commits between `v2.5` and +`v2.6` (inclusive) should be skipped. Cutting down bisection by giving more parameters to bisect start @@ -231,23 +321,23 @@ or bad, you can bisect by issuing the command: $ git bisect run my_script arguments ------------ -Note that the script (`my_script` in the above example) should -exit with code 0 if the current source code is good, and exit with a -code between 1 and 127 (inclusive), except 125, if the current -source code is bad. +Note that the script (`my_script` in the above example) should exit +with code 0 if the current source code is good/old, and exit with a +code between 1 and 127 (inclusive), except 125, if the current source +code is bad/new. Any other exit code will abort the bisect process. It should be noted -that a program that terminates via "exit(-1)" leaves $? = 255, (see the -exit(3) manual page), as the value is chopped with "& 0377". +that a program that terminates via `exit(-1)` leaves $? = 255, (see the +exit(3) manual page), as the value is chopped with `& 0377`. The special exit code 125 should be used when the current source code cannot be tested. If the script exits with this code, the current revision will be skipped (see `git bisect skip` above). 125 was chosen as the highest sensible value to use for this purpose, because 126 and 127 are used by POSIX shells to signal specific error status (127 is for -command not found, 126 is for command found but not executable---these +command not found, 126 is for command found but not executable--these details do not matter, as they are normal errors in the script, as far as -"bisect run" is concerned). +`bisect run` is concerned). You may often find that during a bisect session you want to have temporary modifications (e.g. s/#define DEBUG 0/#define DEBUG 1/ in a @@ -260,7 +350,7 @@ next revision to test, the script can apply the patch before compiling, run the real test, and afterwards decide if the revision (possibly with the needed patch) passed the test and then rewind the tree to the pristine state. Finally the script should exit -with the status of the real test to let the "git bisect run" command loop +with the status of the real test to let the `git bisect run` command loop determine the eventual outcome of the bisect session. OPTIONS @@ -307,12 +397,12 @@ $ git bisect run ~/test.sh $ git bisect reset # quit the bisect session ------------ + -Here we use a "test.sh" custom script. In this script, if "make" +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. +`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 +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. @@ -379,6 +469,26 @@ In this case, when 'git bisect run' finishes, bisect/bad will refer to a commit has at least one parent whose reachable graph is fully traversable in the sense required by 'git pack objects'. +* Look for a fix instead of a regression in the code ++ +------------ +$ 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 +------------ ++ +or: +------------ +$ 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 -------- |