Debugging with git

Git can be used for code archaeology and debugging. We will only look at two commands in some details:

Git blame

A standard git blame annotates every line in a file with the abbreviate commit hash, the commit author and time it was changed. There are a lot of command switches to experiment with, use man git blame to get an overview. We want to look into two of them.

$ git blame filename
8e04d7e0 (Hans 2025-06-22 12:07:49 +0200 1) Line 1
8e04d7e0 (Hans 2025-06-22 12:07:49 +0200 2) Line 2

Finding out from where a line came from

When we refactor code we often move lines between files or inside those files. There are two switches which can help us identify those lines.

Both have a cut-off of 20 chars. Only if at least 20 chars are moved the will detect it. The cut-off can be changed by supplying a number after the switch, e.g. -C5 will reduce it to 5.

$ git blame -C5 filename
8e04d7e0 file2.txt (Hans    2025-06-22 12:07:49 +0200 1) Line 1 
^1b75ab3 file1.txt (maschmi 2025-06-22 12:07:49 +0200 2) Line 2

As we can see, Line 2 is coming from file1.txt and was introduced in commit ^1b75ab3.

Git bisect

If you create small, logical and atomically commits git bisect can go a long way in hunting down a change which introduced unwanted behavior. git bisect needs to have a commit range defined, where one commit is bad, the other one is good. Then it will perform a binary search and asking you every time if the current commit is good or bad. After you are finished you need to end the bisect with git bisect reset. If you have a possibility to test fast if the commit is good or bad this goes a long way in hunting down issues. Sometimes, you may find the issue in a commit you never thought of looking into as the commit message put you on the wrong track.

The methodology is as follow:

# start the bisect
$ git bisect start
# mark the current commit as bad
$ git bisect bad 
# mark another commit as good
$ git bisect good commitHash

# loop from here untill you found the commit
# run your test, decide if it is good or bad
# if the test was good
$ git bisect good
# if the test was bad
$ git bisect bad
# end loop

# if you are finished, exit bisect mode
$ git bisect reset

Exercises

There is a prepared exercise for both commands available: Debugging Exercise.