Learn More About the History of a Line with Git Blame

I’m working on an interesting refactoring project at the moment. Today, I found a strange part in the code and I was really curious who implemented it and why, so I run git blame to learn more about it. Since I cannot share code from the customer’s repository, I’ll use the code from one of my repositories. Let’s say that the Munger.java is not working as it is supposed to work, and the test framework reports problem at line 9:

% git blame -L8,+3 src/main/java/com/zsoltfabok/blog/Munger.java
ab7e2b50 (Zsolt 2012-01-25 00:26:17 +0100  8)   public String munge(String word) {
e26fd52f (Zsolt 2012-02-07 20:45:30 +0100  9)     if (word.length() > 2) {
e26fd52f (Zsolt 2012-02-07 20:45:30 +0100 10)         return word;

It seems that the commit e26fd52f affected that line, let’s see what the change is about:

% git show e26fd52f
commit e26fd52f2de26bb087f63fd70458e75e08540a02
Author: Zsolt Fabok
Date:   Tue Feb 7 20:45:30 2012 +0100

    Indentation fix

     public String munge(String word) {
-        if (word.length() < 2) {
-            return word;
-        } else {
-            StringBuilder temp = new StringBuilder(word);
-            temp = temp.reverse();
-            return switchFirstAndLastCharacters(temp).toString();
-        }
+      if (word.length() < 2) {
+          return word;
+      } else {
+        StringBuilder temp = new StringBuilder(word);
+        temp = temp.reverse();
+        return switchFirstAndLastCharacters(temp).toString();
+      }

This is what I saw during the day: someone did and irrelevant change - indentation fix in this case -, which prevents me from learning about the change that I’m actually interested in. Fortunately, git is the best version control system on the market, and provides some help in cases like this one.

The first solution is for those who like to solve problems using the command line. The blame command accepts a commit which specifies the starting point of the search. If this commit is not specified, blame will use the HEAD as starting point. So in our case the starting point should be one commit below the e26fd52f commit (mind the ‘^’ meaning below) so that the already known indentation problem won’t show up again:

% git blame -L8,+3 "e26fd52f^" -- src/main/java/com/zsoltfabok/blog/Munger.java
ab7e2b50 (Zsolt 2012-01-25 00:26:17 +0100  8)   public String munge(String word) {
30b4cae4 (Zsolt 2012-02-07 20:45:02 +0100  9)       if (word.length() < 2) {
ab7e2b50 (Zsolt 2012-01-25 00:26:17 +0100 10)           return word;

There is another commit - 30b4cae4 - which changed that line, but not the surrounding lines. It’s getting interesting, let’s see what that commit is about:

% git show 30b4cae4
commit 30b4cae49bba4958c5e16a4c414d411de09996bb
Author: Zsolt Fabok
Date:   Tue Feb 7 20:45:02 2012 +0100

    Minor fix based on customer feedback

     public String munge(String word) {
-        if (word.length() < 3) {
+        if (word.length() < 2) {
             return word;

I found the culprit. No test cases, a meaningless commit message, but now I know who to blame for the current problems. Although I like the command line interface of git, this kind of investigation needs a lot of time. I usually use the git gui command for committing - you have to install the gui extension first -, and I’ve learnt today that it also has an option called blame, which does the following:

% git gui blame src/main/java/com/zsoltfabok/blog/Munger.java

With a single command I can see the commits which affected the line I’m interested in. This makes investigation really fast and successful. I hope it’ll also help you narrow down your searches for certain unexplained changes.


comments powered by Disqus