Git has a nice feature called
bisect that's immensely useful for finding out where and when something broke.
For this example, we'll use small integers for commit ids because they're easier to reason about and orderly. In reality, they'll be long SHA hashes.
Let's say you have a commit history like this:
commit 12 Author: Joe commit 11 Author: Scott commit 10 Author: Scott commit 9 Author: Scott commit 8 Author: Miles commit 7 Author: Joe commit 6 Author: Dave commit 5 Author: Bob commit 4 Author: Joe commit 3 Author: Dave
Pretend you're Dave (your last commit was commit 6) and you do a
git pull and an 'install-dev' and see that the site's busted, CSS all over the place, whatever. Git bisect to the rescue. First, tell git you're ready to have it help you find the problem:
$ git bisect start
Now, mark the current commit as "bad":
$ git bisect bad
Note, this doesn't do anything permanent. It just marks a commit temporarily as "bad" (it doesn't change your repo or anything permanent). Now pick a commit that you know was good and mark it as such:
$ git bisect good 6
git will find a commit halfway between the good and bad commit and check it out into your working directory. Now you can test this checkout (e.g.,
make test). If it's good, tell git about it:
$ git bisect good
if it's bad:
$ git bisect bad
git will then bisect (cut in half again) to find another commit halfway between this one and the previous one for you to mark. This repeats until there are no more commits to test.
git will say:
10 is the first bad commit
and show you the offending commit and what file or tree was changed:
10 is the first bad commit commit 10 Author: Scott Date: Fri Feb 1 10:16:54 2013 -0700 - add *.local to exclusion list :040000 040000 82c44e7914e7be2f67fdc0f30387e1f66a677212 e0e88a84b7f247e801028b878b09e98e992c60d4 M lib
You can diff this, etc. to see what changed between this and the previous commit like this:
$ git diff HEAD~1
You don't want to make any actual fixes yet. This tool is just for helping you find the problem. Now you should get back to the last commit of the branch where you were when you started the bisect. Always do this:
$ git bisect reset
which will put your working tree back to where it was after you pulled, but now you know what the problem is and whom to blame :)
If you're fortunate enough to be working on a codebase with regression tests, you can leverage that and let git find the broken commit for you:
$ git bisect run make test
If the result of
make test returns non-zero, git understands that as a failure and marks that commit as bad until it finds the first offending commit—completely automatic.