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.
Copy and paste the following lines:
mkdir git_bisect_tests cd git_bisect_tests git init
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:
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’.
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':
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
.
In this case, it was the ‘Adding the word boat’ commit we picked above.
In this case, let’s use the very last commit in the repository, since we know that had the word ‘car’ in it.
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.
This commit is still bad, so we tell bisect about how bad it is: git bisect bad
Once again, git bisect checked out a new commit halfway between the latest bad commit and the known good commit.
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
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.
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.
Like this article? Check out our top 5 Git tips and tricks
Metal Toad is an AWS Managed Services provider. In addition to this article we recommend checking our article on how to host a website on AWS in 5 minutes.