Clock Blog
Git Bisect: Simple Examples and Automation
Manual Workflow
As projects and their teams grow, so must the amount of time that is invested into isolating latent errors. If your development team utilises source control it can often be useful to narrow your search down to the specific commit which introduced a given issue. Doing this manually can be a tiresome process, fortunately for our fingers Git exposes a way to ferret out offending commits with a technique akin to a Binary Search.
The simplest use of this tool requires you to undertake a small, manual workflow.
- Start git bisect.
# git bisect start - Give git a bad revision.
# git bisect bad {insert your bad revision} - Give git a good revision.
# git bisect good {insert your good revision} - The bisect loop begins.
- Git checks out an alternative commit (Following a Binary Search approach).
- You build and test your application.
- Tell git if the issue is present or not.
# git bisect goodor# git bisect bad - Git narrows it's search and performs another search.
- Eventually git will arrive at the git which introduced the issue.
Voilà! You have located the offending commit; the volume of code you need to inspect has been drastically shortened. (You can check the contents of a given commit using git show {insert commit ref}).
The procedure above is great for locating a bug on a page of a web application for example. But if the output your testing is displayed in the console (Such as status from a build process or unit test), then we can get Git bisect to automate this workflow it's self.
Basic Automation
If you're bisecting to find the introduction of a failed unit test or build of your application, running and waiting for the associated commands to complete can consume a lot of your time. Luckily for our patience, Git bisect can take a command to run against each commit and looks at the command's exit code automatically determine the success of the revision.
# git bisect start {bad revision} {good revision}
# git bisect run {command to run unit tests or build your project}
Nice! This works for a good number of cases but if you want to preform a more precise tests on your output, you can enlist the assistance of a small Shell script.
Custom Automation
The main thing you'll need to be successful in writing your own scripts is a basic understanding of Shell exit codes. At the most basic level an exit code of '0' is for success and anything else denotes an error. As you've probably guessed Git will look to these codes to determine the success of your build script. By grepping the output of my build process I can test for the occurrence of a given string then close my Shell script with an exit code pertaining to the result.
#!/usr/bin/env bash
# Build and grep for failure output. Replace with your own command.
maiden setup development 2>&1 | grep '\"reload\" failed'
# Retrieve the exit code of the grep.
if [ "$?" -eq "0" ]; then
# echo "Text found."
exit 1
else
# echo "Text not found."
exit 0
fi
Now that we've written our test logic, you'll want to put it somewhere outside of your repository, this is to prevent git reacting to your script as an untracked file. This script is one I will (probably) make use of again, so I've gone ahead and put it in a scripts directory setup on my user's path.
Now we're ready to run:
# git bisect start {bad revision} {good revision}
# git bisect run {path to your script}
Git will now perform the binary search based on output provided by your script. This approach can of course be used alongside time intensive unit tests, enabling you to play detective in the background.
Further Reference
- http://www.kernel.org/pub/software/scm/git/docs/git-bisect.html - GIt Bisect manual
- http://en.wikipedia.org/wiki/Binary_search_algorithm - Binary Search
- http://tldp.org/LDP/abs/html/exit-status.html - Shell exit codes
- What was the 2>&1 in the above script?
Like what you've read?