Unfortunately every software developer knows that things are often going wrong. Something breaks the build, something else breaks the tests. Someone makes changes which don’t fit with the coding guidelines etc.
It can be pretty difficult in such cases to figure out what went wrong, long long hours and days of debugging is needed sometimes.
Fortunately git can also help in such situations. Let’s see some builtin git commands which can make your life easier if something went wrong in your project.
You are reading a code and you find a line. “Who the hell did it?” - this is your first question. Maybe you don’t understand the purpose of the line or it is not following the coding guidelines or it is the root cause of a bug. The first thing that you can do is to check the git log for that file and figure out which commit contains the relevant change. It can be time consuming, especially if there’s a long history of the file and the relevant change happened long back in the time.
There’s another, more efficient solution: git blame.
Just type git blame filename. It will show you for each line, which commit was the last one that modified it.
This way it is pretty easy to figure out who did the change and what was its purpose.
You found a bug in the code. You know that a week ago it was still not present and you don’t know the exact root cause yet. It would help a lot if you knew which commit introduced the bug, you could save a lot of debugging-time.
Git bisect is the best solution in this situation. Git bisect is a binary search method in your commit history. It can even handle the merge commits. Let’s see how it works:
- Type git bisect start - It starts the bisect process
- Type git bisect bad - It marks the current commit as “bad”
- Type git bisect good hash_of_the_last_working_commit - Mark “good” the last commit where you are sure the bug was not present
- Now git bisect will checkout a commit which is between the current and the last good commit. Compile it and test it. If the bug is present type git bisect bad, otherwise git bisect good.
- Repeat step 4 until you can’t find the commit
Thanks for the power of binary search, it is a pretty fast method to find the guilty commit.
It can cause issues with this method if the bug is not consistent, it randomly appears in some commits.
It can be time consuming to test the commits manually.
Fortunately it can be automated. Git bisect also supports running automated tests.
- Implement a test which return 0 if the bug is not present and non zero if the bug is present (most of the test frameworks already works in this way, so it is enough to implement some simple unit test in most of the cases)
- Type git bisect start
- Type git bisect bad
- Type git bisect good hash_of_last_working_commit
- Type git bisect run your_test
This method will find the first commit where your bug is present.
Both git blame and git guilty can be very useful in situations when you have to figure out what is the root cause of a bug. It can be much faster than using a classical debugging approach, given that you committed frequently enough.