Debugging with Git

Learn how to debug using Git’s Blame and Bisect

Shaumik Daityari
Bits and Pieces

--

Image by mohamed Hassan from Pixabay

This post talks about two Git techniques to debug errors in your codebase — blame and bisect. Git blame helps you describe the details of each line in a file, while bisect performs a binary search through your commits. Blame and bisect help you solve bugs in large codebases by finding out the root commit that introduced an issue.

Tip: Use Bit to easily reuse small modules across projects, for easier testing and maintenance. Build truly modular JavaScript projects and kill the overhead around code reuse, to build faster.

Prepare Files for Debugging

To demonstrate the debugging features of Git, we will use a repository hosted on GitHub so that you can run the commands and replicate results. To clone the repository, run the following command:

git clone https://github.com/sdaityari/my_git_project/

Once the cloning process is complete, change the active directory to the recently cloned folder.

cd my_git_project
ls -al

Let us explore the files in the repository.

drwxr-xr-x   9 shaumik  staff   288 Sep 22 17:24 .
drwxr-xr-x+ 40 shaumik staff 1280 Sep 22 17:24 ..
drwxr-xr-x 12 shaumik staff 384 Sep 22 17:24 .git
-rw-r--r-- 1 shaumik staff 63 Sep 22 17:24 data.csv
-rw-r--r-- 1 shaumik staff 226 Sep 22 17:24 my_file
-rw-r--r-- 1 shaumik staff 69 Sep 22 17:24 myfile2
-rw-r--r-- 1 shaumik staff 26 Sep 22 17:24 myfile3
-rw-r--r-- 1 shaumik staff 220 Sep 22 17:24 sum.py
-rw-r--r-- 1 shaumik staff 591 Sep 22 17:24 tests.py

Further, to check the history of the repository, run the git log command with the --oneline option. To read about basic Git commands, you may wish to explore the trunk workflow of Git.

git log --oneline

The output of the git log command is the history of the project.

c76ee85 (HEAD -> master, origin/master, origin/HEAD) Update data.csv
0d0d493 Added csv data
083e7ee Added yet another test
49a6bec Added more tests
5199b4e ERROR COMMIT: Introduced error in sum.py
b00caea Added tests.py
b117516 Dummy Commit after adding sum.py
7d1b1ec Added sum.py
...
f934591 - Changed two files - This looks like a cooler interfact to write commit messages
8dd76fc My first commit

The commit #5199b4e is the commit that introduced an error in the file sum.py. The file contains a basic function written in Python that adds two numbers.

This tutorial works with both of Git’s methods to debug erros in your code. Let’s get started with Git blame.

Debugging through File History

If you know the source file that is leading to the error, you can use the blame command to arrive at the commit that introduced the change. As described, the error has been deliberately introduced into the sum.py file, so let us run the blame command on the file.

git blame sum.py

The output of the blame command is as follows:

7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530  1) #add_two_numbers.py
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530 2) def add_two_numbers(a, b):
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530 3) '''
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530 4) Function to add two numbers
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530 5) '''
5199b4e1 (Shaumik 2015-05-10 00:50:09 +0530 6) addition = 0 + b
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530 7) return addition
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530 8)
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530 9) if __name__ == '__main__':
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530 10) a = 5
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530 11) b = 7
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530 12) print add_two_numbers(a, b)

The command prefixes each line of the file with the commit hash, author and time of the commit. Notice that the error is in the sixth line of the file, where zero is added to the variable b, instead of the variable a. The output of the blame command is sufficient to know that the commit with the hash #5199b4e1 introduced this bug into the code.

To list the changes about the commit #5199b4e1, run the git show command.

git show 5199b4e1

The output of the git show command lists down the changes in the commit.

commit 5199b4e10ba04b63ed1e76118259913123fbf72d
Author: Shaumik <sdaityari@gmail.com>
Date: Sun May 10 00:50:09 2015 +0530
ERROR COMMIT: Introduced error in sum.pydiff --git a/sum.py b/sum.py
index 7a3d629..085beee 100644
--- a/sum.py
+++ b/sum.py
@@ -3,7 +3,7 @@ def add_two_numbers(a, b):
'''
Function to add two numbers
'''
- addition = a + b
+ addition = 0 + b
return addition
if __name__ == '__main__':

As seen in the output, notice that the only change in that commit was the line in question. Once you have zeroed down on the commit that has introduced the change and the changes made in that commit, you can proceed with fixing the error.

Debugging through Binary Search

Git’s blame command is helpful when you are aware of the file which introduced the change. Imagine a scenario where you can see the effect of a bug but aren’t sure which part of the code leads to it! In such cases, Git bisect comes to the rescue.

To start with the process, you need to identify a commit from the history where the bug was not present, essentially a “good” commit. The aim of the bisect process is to find a commit between that “good” commit and the current “bad” commit, which introduced the bug. When you initiate Git’s bisect process, you start a wizard and your repository goes into a temporary mode. In each step, the wizard changes the state of the repository to an intermediate commit and asks you if the bug is present. The process continues until the first “bad” commit is identified.

Let us start the bisect wizard.

git bisect start

Next, you need to specify the good and bad commits to start the wizard. Let us select the first commit in the history of the repository, #8dd76fc as the good commit.

git bisect good 8dd76fc

Since the latest commit has the error, let us label that as the bad commit.

git bisect bad c76ee85

Once you have fed the good and bad commits, the wizard asks you if the error still exists by changing the state of the repository.

Bisecting: 9 revisions left to test after this (roughly 3 steps)
[cafb55dde0af6e3ae300c1ba5e68a41fd49f7362] Merge commit '5ef655a4caf8'

Notice that we have nine commits, hence we would require roughly three steps (since 2 raised to the power 3 is 8, which is very close to 9). If we had a thousand commits, we would require about ten steps (as it is a binary search process).

At each step, you need to check if the error is present and feed either git bisect good or git bisect bad.

$ git bisect good
Bisecting: 4 revisions left to test after this (roughly 2 steps)
[b00caea53381979ec1732d919d6f76e3baaf80fc] Added tests.py
$ git bisect good
Bisecting: 2 revisions left to test after this (roughly 1 step)
[49a6bec7c629e5a84e07c55301f2447f890bad4c] Added more tests
$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[5199b4e10ba04b63ed1e76118259913123fbf72d] ERROR COMMIT: Introduced error in sum.py
$ git bisect bad
5199b4e10ba04b63ed1e76118259913123fbf72d is the first bad commit
commit 5199b4e10ba04b63ed1e76118259913123fbf72d
Author: Shaumik <sdaityari@gmail.com>
Date: Sun May 10 00:50:09 2015 +0530
ERROR COMMIT: Introduced error in sum.py:100644 100644 7a3d629df3e91534e7b0cbe082694bee257294d7 085beeea8b099ec16e923ca780d48241906aec8c M sum.py

You can see that it has successfully identified the commit which introduced the error.

To come out of the bisect wizard, run the reset command.

git bisect reset

Automate Git Bisect Process

If you would like to remove the manual part of the Git bisect process, you can automate the process through unit tests. You may write a script that detects if the error is present. Once you have a script ready, you can run the following commands:

git bisect run [command to run tests]

If the command to run your tests are python tests.py replace the second command by the following:

git bisect run python tests.py

Conclusion

In this tutorial, we have used a simple example to explain two dynamic and useful Git tools. To summarise, if you know the source file of an error, you can proceed with the Git blame command. On the other hand, if you are only aware of the behaviour of a bug, use the bisect process.

Does Git debugging fit into your development process? What is the most essential tools that you use to debug your code? Do let us know in the comments.

Learn More

--

--