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

Either way, 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.