I have read some articles saying that git bisect
is awesome, however I'm not native speaker and I can't understand why it's awesome.
Could you please demonstrate on some code sample what is so amazing about it? Is it just like svn blame
?
I have read some articles saying that git bisect
is awesome, however I'm not native speaker and I can't understand why it's awesome.
Could you please demonstrate on some code sample what is so amazing about it? Is it just like svn blame
?
Just to add a further point:
We can specify a file name or path to
git bisect start
in case we know that the bug has come from particular files. For example, Suppose we knew that the changes that caused the regression were in the com/workingDir directory then we can rungit bisect start com/workingDir
This means that only the commits that changed the contents of this directory will be checked, and this makes things even faster.Also,If it’s difficult to tell if a particular commit is good or bad, you can run
git bisect skip
, which will ignore it. Given there are enough other commits, git bisect will use another to narrow the search instead.git bisect run
automatic bisectIf you have an automated
./test
script that has exit status 0 iff the test is OK, you can automatically find the bug withbisect run
:This supposes of course that if the test script
./test
is git tracked, that it does not disappear on some earlier commit during bisection.I have found that very often you can get away by just copying the in-tree script out of tree, and possibly playing with
PATH
-like variables, and running it from there instead.Of course, if the test infrastructure on which
test
depends breaks on older commits, then there is no solution, and you will have to do things manually, deciding how to test commits one by one.More tips
Stay on the first failing commit after bisect instead of going back to
master
:start
+ initialbad
andgood
in one go:is the same as:
See what has been tested so far (by manual
good
andbad
orrun
):Sample output:
Show good and bad refs on git log to get a better notion of time:
This only shows commits with a corresponding ref, which reduces the noise grealy, but does include autogenerated refs of type:
which tell us which commits we marked as good or bad.
Consider this test repo if you want to play around with the command.
Failure is fast, success is slow
Sometimes:
For those cases, e.g. supposing the failure always happens withing 5 seconds, and if we are lazy to make the test more specific as we really should, we can use
timeout
as in:This works since
timeout
exits124
while the failure oftest-command
exits1
.Magic exit statuses
git bisect run
is a bit picky about exit statuses:anything above 127 makes the bisection fail with something like:
In particular, a C
assert(0)
leads to aSIGABRT
and exits with status 134, very annoying.125 is magic and makes the run be skipped with
git bisect skip
See
man git-bisect
for the details.So you might want to use something like:
Tested on git 2.16.1.
$ git bisect ..
bascically a Git tool for debugging. 'Git Bisect' debugs by going through the previous commits since your last (known) working commit. It uses binary search to go through all those commits, to get to the one which introduced the regression/bug.$ git bisect start
# Starting bisect$ git bisect bad
# stating that the current commit (v1.5) has the regression/ setting 'bad' point$ git bisect good v1.0
# mentioning it the last good working commit (without regression)This mentioning of 'bad' and 'good' points will help git bisect (binary search) pick the middle element (commit v1.3). If the regression is there at commit v1.3, you'll set it as the new 'bad' point i.e. (Good -> v1.0 and Bad -> v1.3)
or similarly if the commit v1.3 is bug-free you'll set it as the new 'Good point' i.e. (*Good -> v1.3 and Bad -> v1.6).
The idea behind
git bisect
is to perform a binary search in the history to find a particular regression. Imagine that you have the following development history:You know that your program is not working properly at the
current
revision, and that it was working at the revision0
. So the regression was likely introduced in one of the commits1
,2
,3
,4
,5
,current
.You could try to check out each commit, build it, check if the regression is present or not. If there is a large number of commits, this can take a long time. This is a linear search. We can do better by doing a binary search. This is what the
git bisect
command does. At each step it tries to reduce the number of revisions that are potentially bad by half.You'll use the command like this:
After this command,
git
will checkout a commit. In our case, it'll be commit3
. You need to build your program, and check whether or not the regression is present. You'll also need to tellgit
the status of this revision with eithergit bisect bad
if the regression is present, orgit bisect good
if it is not.Let's suppose that the regression was introduced in commit
4
. Then the regression is not present in this revision, and we tell it togit
.It will then checkout another commit. Either
4
or5
(as there are only two commits). Let's suppose it picked5
. After a build we test the program and see that the regression is present. We then tell it togit
:We test the last revision,
4
. And since it is the one that introduced the regression, we tell it togit
:In this simple situation, we only had to test 3 versions (
3
,4
,5
) instead of 4 (1
,2
,3
,4
). This is a small win, but this is because our history is so small. If the search range is of N commits, we should expect to test 1 + log2 N commits withgit bisect
instead of roughly N / 2 commits with a linear search.Once you've found the commit that introduced the regression, you can study it to find the issue. Once this is done, you use
git bisect reset
to put everything back on the original state before usinggit bisect
command.Note: the terms
good
andbad
are not the only ones you can use for marking a commit with or without a certain property.Git 2.7 (Q4 2015) introduced new
git bisect
options.With documentation adding:
See commit 06e6a74, commit 21b55e3, commit fe67687 (29 Jun 2015) by Matthieu Moy (
moy
).See commit 21e5cfd (29 Jun 2015) by Antoine Delaite (
CanardChouChinois
).(Merged by Junio C Hamano --
gitster
-- in commit 22dd6eb, 05 Oct 2015)TL;DR
Start:
Bisecting: X revisions left to test after this (roughly Y steps)
Repeat:
Issue still exists?
$ git bisect bad
$ git bisect good
Result:
When Done: