Showing posts with label debugging. Show all posts
Showing posts with label debugging. Show all posts

5/06/2021

Find the commit which broke the test in git

Scenario

Find the first broken git commit.

Scenario in details

However the main purpose of git is version control, it can be also useful for debugging.

You found a bug in the system, your first two questions are of course: who did it and when?

Let git help you to figure it out in a fast way.

Detailed description of the solution

Case 1 - Manual verification of commits

If you don’t have an automated way to verify if a commit contains the bug or not, then follow case 1.

The solution will be git bisect. You can enter bisect mode with the command git bisect start.

Then you have to mark your current commit bad, as it contains the bug. Type the git bisect bad command. As the next step you have to mark the last known good commit, so a commit where the bug was still not present. For that you may have to try out several commits. But if you remember that it was still working 2 days ago, then just pick a commit from that day. You can checkout each commit to test. Once you found a good commit use the command git bisect good hash_of_the_good_commit. If the current head is the good commit you can skip the hash from the end of the command.

Now git bisect will checkout some commits. Determine for each if they contain the bug or not and mark them with git bisect good or git bisect bad. After several steps Git bisect will tell you the first good commit. If you think you made a mistake you can restart the bisect process anytime, just type git bisect reset.

Case 2 - Automated verification of commits

You can make this process faster if you have a script or any executable which can determine if the bug is present or not. You can even use a test framework. The point is only that the executable shall return 0 if the bug is not present and anything else if the bug is present.

Similarly to case 1 enter bisect mode with the command git bisect start.

Then you have to mark your current commit bad, as it contains the bug. Type the git bisect bad command. As the next step you have to mark the last known good commit, so a commit where the bug was still not present.

Once you marked one good and one bad commit just use the command git bisect run path_to_your_executable. Here the executable is either a standalone script, but it can be even a call to your test framework with some parameters.

After this step git bisect shows you the first bad commit.

Step-by-step guideline

Case 1 - Manual verification of commits

  1. Type git bisect start - It starts the bisect process

  2. Type git bisect bad - It marks the current commit as “bad”

  3. Type git bisect good hash_of_the_last_working_commit - Mark “good” the last commit where you are sure the bug was not present

  4. 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.

  5. Repeat step 4 until you can’t find the commit

Case 2 - Automated verification of commits

  1. Implement a test which returns 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)

  2. Type git bisect start

  3. Type git bisect bad

  4. Type git bisect good hash_of_last_working_commit

  5. Type git bisect run your_test

Test your knowledge

You can test your knowledge here:

https://github.com/lmarcell/git_practical_exercises_bisect


Additional git material

You can find more useful information related to git in the following ebook:

5/18/2020

Advanced GIT Tutorial - How to debug your code with GIT?

Introduction

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.

Figure Out, Who Introduced The Guilty Line

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.

Find The First Broken Commit

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:
  1. Type git bisect start - It starts the bisect process
  2. Type git bisect bad - It marks the current commit as “bad”
  3. Type git bisect good hash_of_the_last_working_commit - Mark “good” the last commit where you are sure the bug was not present
  4. 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.
  5. 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.

Automatize The Search Process

It can be time consuming to test the commits manually.
Fortunately it can be automated. Git bisect also supports running automated tests.
  1. 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)
  2. Type git bisect start
  3. Type git bisect bad
  4. Type git bisect good hash_of_last_working_commit
  5. Type git bisect run your_test
This method will find the first commit where your bug is present.

Summary

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.

How I prepared my first online course

Since long I didn't publish anything here. It's because I was busy with some other topics, but now it's time to share the result...