git bisect

A beginner's guide to GIT BISECT - The process of elimination

Filed under:

Metal Toad is an AWS Managed Services provider. In addition to this article we recommend checking out Tony's latest on how to host a website on AWS in 5 minutes.

Like this article? Check out our top 5 Git tips and tricks

The slowest, most tedious way of finding a bad git commit is something we've all done before. You checkout some old commit, make sure the broken code isn't there, then checkout a slightly newer commit, check again, and repeat over and over until you find the flawed commit.

Using git bisect is a much better way. It's like a little wizard that walks you through recent commits, asks you if they are good or bad, and narrows down the broken commit. In this blog post, I encourage you to create a fresh git repository and walk through each step. Hopefully, you'll gain an intrinsic understanding of git bisect by the end of the exercise.

Setting up your playground

  1. Create an experimental git repository.

    Copy and paste the following lines:

    mkdir git_bisect_tests
    cd git_bisect_tests
    git init
  2. Create a history of commits to play with.

    Copy and paste the following lines. This will create a commit history for a file called ‘test.txt’ that contains the opening lyrics to the childrens song “Row Row Row Your Boat”.

    echo row > test.txt
    git add -A && git commit -m "Adding first row"
    echo row >> test.txt
    git add -A && git commit -m "Adding second row"
    echo row >> test.txt
    git add -A && git commit -m "Adding third row"
    echo your >> test.txt
    git add -A && git commit -m "Adding the word 'your'"
    echo boat >> test.txt
    git add -A && git commit -m "Adding the word 'boat'"
    echo gently >> test.txt
    git add -A && git commit -m "Adding the word 'gently'"
    sed -i -e 's/boat/car/g' test.txt 
    git add -A && git commit -m "Changing the word 'boat' to 'car'"
    echo down >> test.txt
    git add -A && git commit -m "Adding the word 'down'"
    echo the >> test.txt
    git add -A && git commit -m "Adding the word 'the'"
    echo stream >> test.txt
    git add -A && git commit -m "Adding the word 'stream'"

    Output:

  3. Find the bug in ‘test.txt’ file.

    Look at the contents of test.txt. There is a glaring error: the word ‘car’ is where the word ‘boat’ should be. That happened during our commit history – at some point, the commit of the word ‘boat’ was overwritten by the commit for the word ‘car’.


The Experiment

  1. Use git log to find a good commit, and a bad commit.

    First off, let’s try to find a commit that still had the word ‘boat’, and not the word ‘car’. Check out your git log:


    We know that the newest commit in the log is bad, so we will classify this as our bad commit. For the sake of simplicity, let’s say our good commit is the first commit we made for the word 'boat':

  2. With a good commit, and a bad commit, we’re ready for the process of elimination – git bisect

    Git bisect is like a wizard: it guides you step by step through a process of elimination until you find the commit that broke your code. Once you type git bisect start, you have started the wizard and it won’t end until you type git bisect reset.

  3. Start up the git bisect wizard

  4. Let the git bisect wizard know of a good commit.

    In this case, it was the ‘Adding the word boat’ commit we picked above.

  5. Let the git bisect wizard know of a bad commit.

    In this case, let’s use the very last commit in the repository, since we know that had the word ‘car’ in it.

  6. Look at the contents of test.txt

    When we typed git bisect bad in this step, git bisect checked out an old commit for us – the commit halfway between the latest bad commit and the known good commit. This is how bisect works – it cuts the commit history down in halves until it finds the original bad commit.

  7. The word 'car' is still there = BAD!

    This commit is still bad, so we tell bisect about how bad it is: git bisect bad

  8. Look at the contents of test.txt again.

    Once again, git bisect checked out a new commit halfway between the latest bad commit and the known good commit.

  9. The word 'boat' is there = GOOD!

    Now we see the word ‘boat’, so this is a good commit. Let’s let git bisect know how good it is: git bisect good

  10. ALL DONE - The bad commit has been found!

    Plain as day, git reports back to you: “I found the first bad commit”

    You are now free to investigate the problem, notify the author, write patches, and take care of business.

  11. To end your git bisect wizard, simply type git bisect reset

With git bisect, I've been able to narrow down broken code within a few seconds on repositories with a dozen developers adding several dozen commits per hour. I almost never use any other technique to find broken code.

Date posted: April 19, 2012

Comments

If you are exceedingly lazy you can even let Git perform the good / bad check via the "run" option.

Is this yet another example of why Git is better then SVN, or is there an analog in subversion land?

Binary search of commits is common in most source control solutions, so this won't help in a SVN v. Git debate :) It's best to focus on the speed of day-to-day operations and distributed nature of git to win that debate.

I don't see how this solves anything. You still have to review what the changes are and look at differences.

It gives you the indication of where in history the failure started.
If there's a long list of commits, it can take a long time to isolate the change. So, having the computer check half-way between good and bad, then halfway again, etc. can isolate the change down to a single commit.

Hi, if we run git blame for the file, we can find the commit where the word boat was introduced. Why go through this whole process? I am just trying to think of a use case.

Git-blame is a different use case, for when you already know what code to look at. Git-bisect is used when you know the behavior that changed, but not what code caused it.

Your demonstration could be solved by blame too which got me confused! Butthe comment clears it up! Thanks :)

Simple, elegant, and direct tutorial. I'm a fan!

Thanks! Helped me fix a bug my debugger couldn't help me with.

Juse wanna bump the comment of

"Git-blame is a different use case, for when you already know what code to look at. Git-bisect is used when you know the behavior that changed, but not what code caused it."

the example shown here can easily be resolved with git blame so the biggest use case of git bisect really is when you don't know what code caused a problem. I assume that while using git bisect, you test the behaviour on every bisect.

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <cpp>, <java>, <php>. The supported tag styles are: <foo>, [foo].
  • Web page addresses and email addresses turn into links automatically.
  • Lines and paragraphs break automatically.

Metal Toad is an Advanced AWS Consulting Partner. Learn more about our AWS Managed Services

Schedule a Free Consultation

Speak with our team to understand how Metal Toad can help you drive innovation, growth, and success.