1

In git, we have bisect to conveniently find the first bad commit, in this way:

git bisect start linux-next/master v2.6.26-rc8
git bisect run make kernel/fork.o

But the prerequisite is I know which old commit is good. In this example, it is v2.6.26-rc8.

What happens if I don't know which commit is good?

Is it possible to write a script, to reversely loop through the git commits, begin from current HEAD, from latest to oldest, and automatically test each commit, until the first good?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
huangyingw
  • 89
  • 6
  • 2
    You don't have to name a commit straight away. You can run `git bisect start` bare to get it started, then go look through the history at your leisure. Test an old commit, then mark it with either `git bisect good` or `git bisect bad`. Once you've identified one of each `git bisect` will walk you through the rest of the bisection process. – John Kugelman Jun 24 '22 at 04:02
  • (Going backwards one commit at a time is exactly the sort of tedious process `bisect` is helping you to avoid!) – John Kugelman Jun 24 '22 at 04:04
  • ok, your suggestion is a good/better practice of using bisect. I am thinking of a script to auto test the commits reversely, and let it run over night:) – huangyingw Jun 24 '22 at 04:11
  • That's not a bisect, though. That's just a straight linear search... You don't need `bisect` if you're going to check every commit one-by-one. – John Kugelman Jun 24 '22 at 04:15
  • 1
    What you're supposed to do is make an educated guess at where the culprit is. Jump back a hundred, or a thousand commits, whatever, and test it. Remember you don't have to find the *first* good commit, you just need to find *any* good commit. Heck, you can even just mark the *very first commit* of the project good. Let `bisect` run over the entire commit history if you have no better idea of where to start. "The latest commit is bad. The first commit is good. Whatever. Just go already!" – John Kugelman Jun 24 '22 at 04:19

1 Answers1

6

git bisect does a binary search through the commit history. good and bad simply provide boundaries for this search. Git then searches within that range for a commit which is "bad" and the previous one was "good".

All that matters is the "good" commit is before the feature broke, and the "bad" commit is after the feature broke. If you're not sure when the feature broke, pick a commit before the feature was introduced.

If you're not sure, pick a really old commit. You can even pick the first commit. This isn't as absurd as it sounds. Binary searches are very efficient; 10,000 commits can be searched in just log2(10000) tries or 13 tries.

For example, let's say your commit history looks like this.

a - b - c - d - e - f - g - h - i [main]

You know the feature is broken now, you don't know when it was good, but you do know it was introduced at d. Pick c, the commit immediately before the feature was introduced, as the "good" commit.

$ git bisect start
$ git bisect bad
$ git bisect good c

                               HEAD
a - b - c - d - e - f - g - h - i [main]
        g                       b

Then git bisect will do a binary search of d - e - f - g - h until it finds a bad commit immediately after a good one.

In this case it will start with f. Let's say that's bad.

$ git bisect bad

                   HEAD
a - b - c - d - e - f - g - h - i [main]
        g           b           b

Git assumes everything after f is also bad. Then it might try d. Let's say that's good.

$ git bisect good

           HEAD
a - b - c - d - e - f - g - h - i [main]
        g   g       b           b

Then it will try e. Let's say that's bad.

$ git bisect bad

               HEAD
a - b - c - d - e - f - g - h - i [main]
        g   g   b   b           b

e broke the feature.

Schwern
  • 153,029
  • 25
  • 195
  • 336