Check out a free preview of the full Everything You'll Need to Know About Git course

The "Bisect" Lesson is part of the full, Everything You'll Need to Know About Git course featured in this preview video. Here's what you'd learn in this lesson:

ThePrimeagen explains how to use the `git bisect` command to search through Git commits and find a bug or regression. He discusses the properties of bisecting, such as cutting the search space in half with each test, and demonstrates how to use the `git bisect` command to find the commit where the bug occurred. How to automate the process using the `git bisect run` command is also demonstrated in this lesson.

Preview
Close

Transcript from the "Bisect" Lesson

[00:00:00]
>> Honestly, log searching tends to be a drag, often doesn't work. If I could spend one minute looking at the logs to find a bug that could take me two hours to find, of course I'll always make that trade off while it's shot in the dark. But most of the time you have to do this.

[00:00:12]
Get bisect. Bisect works by searching through gits commits for you, and you get to mark if something's good or bad, however you decide, it's good and bad. And then it will do the legwork to determine which commit you should look at. So it's pretty clever. There's some unique properties that make this true.

[00:00:32]
All commits are ordered. I've been saying this, I intentionally said this is that the order of commits is effectively timed, which means that if If I go back one commit, that commit should be further back in time. And so you can kind of see how that would work.

[00:00:47]
That means if I go halfway back, I've gone halfway through or effectively our project's lifecycle of some sort, however, if they're evenly spaced out. So everything is in order, which means it kind of acts like an ordered array, correct? In some sense, yeah, it's like an ordered array.

[00:01:04]
Another thing that you need to have for bisect is that you need to know the two changes. It doesn't matter how far apart they are. Let's just say you know that it's currently broken, so you go back 1,000 commits, and it's working. That's fine. You just need a point in time in which there's two changes.

[00:01:18]
That's it. So let's talk about property one, because I think it's really interesting. If it currently fails and you go back 10 commits and it's still failing, what can you say about going back 9 commits? Is it gonna pass or fail? How about eight commits, fail, seven commits, fail, six, five, four, three, two, one.

[00:01:38]
All of them are going to fail, right? That's the idea of Git bisect, is that due to time and assuming that the bug isn't somewhere highs and bug floating in and out of space, you should be able to quickly go to the correct solution. So to kind of put it visually, if you had commit a and commit b and you have no idea where it's failing at.

[00:01:58]
If you picked the middle commit c and you test it, If c works, what can you say about this graph?
>> The problem lies between c and whatever followed it.
>> C and b, right? You've cut the space in half where the problem could be, right? Yay, or, yeah, the problem lies by just say it inverted, a through c is good.

[00:02:27]
And this other side is unknown. And so the exact opposite is true given the exact same situation again, if c fails, what can we say? Well, we can say that between c and b, it's bad and between c and a, we just don't know yet. So we don't know if it's good or bad.

[00:02:43]
We just know it's bad at c, so it's bad all the way up to b. So that means we can cut half the space every single search. And this is the fundamental for binary search. This is, if you think about a binary tree, walking binary tree, it's the exact same kind of principle in general.

[00:03:02]
This, we're just doing it with commits instead.
>> Does using bisect make an argument against rebase since it needs to be in order?
>> No, rebase, I mean it's about your history of your branch. I mean, you've moved your stuff forward, but at some point, it's committed and it's in the branch or it's in.

[00:03:20]
So yeah, if you move your stuff forward and you test it and it's still broken, then it's broken until you find a working commit. It doesn't really change anything. All right, by the way, I don't know if you know this, but Frontend Masters has a free algorithm course.

[00:03:35]
I heard the guy that teaches it, it's pretty cool. That's what I've been told. Kind of sounds like Gilbert Godfrey though, or Charlie Day, wish Charlie Day. Yeah, that's another one that someone said to me, and it really hurt my feelings. Anyways, it's full free. Hashtag ad, everybody, hashtag ad.

[00:03:50]
Okay, so suppose you don't need to know anything about the bug. You don't need to rely on commit messages, you don't need to rely on anything other than a way to test to see if it is working or not working. It's the fastest way to search a sort of space is via cutting the space in half every single time.

[00:04:06]
There's no faster way. Unless if you have some sort of HashMap. Then once you know where the good and bad are, right, that's hash mapping. You don't have to search only for a bug. So if there's a performance regression, say there's a performance improvement, say there's anything and you want to find it happening.

[00:04:20]
If you have a test that you can prove that it does and doesn't happen, you can bisect your way to the commit that changed whatever. So it's a way to do change detection more than anything else. The only con is that if it takes a lot of time to test and you could do some alternative means to find the change, maybe a quick log search will be your best friend.

[00:04:40]
Just to like give a shot in the dark as opposed to having to deal with bisect for hours if it takes a long time. Anyways, so you get the idea. So when you cut space in half, it's log of n. So it takes seven searches to go through 128 commits, one search to go through one commit, right?

[00:04:55]
So it doesn't grow very fast at all, grows logarithmically. It's very fantastic. All right, so the basics of bisect, all you do is you say git bisect start, then you say get bisect bad saying, hey, the current commit's bad. Then you select a good commit, and then at that point, you test and you just tell it whether it's good or bad.

[00:05:13]
Just start checking out stuff until it gets to the exact point in which it found the error. So you just keep on doing this over and over again until it stops. So we're gonna do the exact same thing. We're gonna take the first commit of the repo and the current tip of master and we're gonna try to find where does it break.

[00:05:30]
So git bisect start, step one. Then git bisect bad. So I'm saying this commit is the bad commit. Now we need to get the very first commit of the repo. There's a lot of different ways to do it. So I'll just go like this, git log --oneLine. This is just very, very easy.

[00:05:51]
There it is right there. So I'll just copy this one out, the b56ed57. And then I can go git bisect good right there. So I'm gonna search the entire repo from beginning to end. There we go. It says bisecting 11 revisions roughly four steps. So is this one good or bad?

[00:06:14]
I'll go like this, npm run test.
>> I wanted to say binary search so much when you're talking about that. I was just thinking, it's right there.
>> It's right there. All right, look at that, it failed. Okay, by the way, npm run, it doesn't run it once.

[00:06:27]
It just keeps it on watch mode, because by test default, apparently it's watch. So that means we need to go git bisect bad. And there it goes. There's five revisions left, roughly three steps. Look at that. This one passed, fantastic. So I'll say, git bisect good. All right, two revisions left, roughly two steps.

[00:06:51]
Let's run test. All right, look at that, it passed. So we'll do a little git bisect good. And now there are zero revisions left. This is the last step. I'll run it once more, and now either the commit I'm on is the good one or the bad one.

[00:07:06]
And so it's able to tell if it's good, that means the next commit over is the bad one, the offending commit, the bad change, or this is the offending change. And so it'll be able to tell with this last test. I refuse to git rebase this, I refuse.

[00:07:21]
We will experience the wait together. All right, so this one failed. So I just got to go like this, git bisect bad. And porque maria, whoa, right there. It says right here. It says apparently zero steps left, which is a little suspicious. Okay, well, we gotta run the test once more, apparently.

[00:07:45]
I'm not exactly sure why this one went this way. In all the times I did it, it actually was done after four of them. But I guess we're gonna wait, one last 30 seconds. Porque 972fasa. Well, look at that. Git bisect bad. So tells you right here, this one is where it went wrong.

[00:08:13]
And this is the commit, in fact, which went wrong. So it was able to go through and we're able to kind of find where the problem was. But here's the deal. Was that kind of annoying? Was that like not a fun experience? Here, I'm gonna scroll all the way through this, you can automate it.

[00:08:28]
So, well, let's do it again, but this time let's add the word run to it, okay? So I'm gonna go here and I'm gonna go, let's see. Git status, git a bisect reset. We're back at the tip. So now we just gotta go like this, git bisect start, git bisect bad, and git bisect good, right here.

[00:08:54]
And then go git bisect run. And then I think it's, what is it? It's, node_modules/ .bin/vitest --run. If you do --run, it doesn't try to watch. Therefore, it'll just quit, right? We'll do that. And now all we have to do is just wait. Just a little bit of waiting.

[00:09:22]
By the way, I see some people saying they didn't know that this existed. This is why it's really good to always just do a quick little run through of the friendly manual or a couple git searches, and just kind of know how the things work or how people use it.

[00:09:34]
Because often you'll find that you're doing something fairly inefficient when the better thing is just right around the corner. Look at this. Hey, look at that. It found the commit. Look at that. We didn't even do anything. Found the commit right here. How nice is that? So bisect run is really nice.

[00:09:48]
You should definitely use bisect run if you have a problem, especially if it can be boiled down to a quick test to run. Beautiful, right?

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now