Mastering Git and GitHub (4 Blogs)
AWS Global Infrastructure

DevOps

Topics Covered
  • DevOps (78 Blogs)
  • Mastering Git and GitHub (4 Blogs)
  • Docker (9 Blogs)
  • DevOps Engineer Masters Program (7 Blogs)
SEE MORE

Git bisect: How to identify a bug in your code?

Last updated on Sep 19,2019 10.7K Views

Divya Bhushan
A passionate Content Developer with key skills – Git, Dockers, Databases, Linux... A passionate Content Developer with key skills – Git, Dockers, Databases, Linux and Unix.
9 / 10 Blog from Git & GitHub

My code was working fine until yesterday, but not until a recent pull from the remote repository broke the code!!!

If you are in a similar situation and don’t know what change broke the code or who out of many contributors owns this bug/feature, then git bisect is your way out. So, in this article on git bisect you will learn how the ‘git bisect‘ command comes to developers rescue in detecting the first bad commit that introduces the bug using the binary search algorithm.

The topics covered in this article are as follows:

Why use git bisect?

There is no doubt in the fact that you tend to create a number of commits for every minor change in Git. In such a scenario, debugging the code becomes a tedious task, as you have to manually go back in time to every single revision of the project snapshot in order to test the working code and detect the bug. Now, this gets even more complex when you have other’s work to inspect without a lead point,  also to request each one to clean up their own mistakes does not sound very feasible either.
Along the way, you might also create and discard a number of ‘feature’ (or hotfix) branches in the process and end up wasting time and effort while deviating from the main line of development.

So, to avoid such scenarios, you can use the git bisect command to find the bad project revision(or snapshot) and eventually fix it with the git revert command.

How does ‘git bisect’ search?

This command bisects (divides) your history between the good and the bad commit range. It points your current project state to a mid-range commit snapshot. The git bisect command then moves through every commit id between this range while pausing at each snapshot to allow you to test the code. If the bug exists, you declare the commit as bad, if not as good unless the search ends.

Syntax

git bisect <subcommand><options>

To understand git bisect better, let us create a project that develops the code for a simple navigation app to be used in a car.

Initial project setup

To create a project that develops the code for a simple navigation app to be used in a car, you can follow the below steps:

Step 1: Create a new directory in your $HOME folder:

cd $HOME
mkdir my_nav_app

Step 2:  Navigate to the new directory:

cd $my_nav_app

Step 3:  Clone to download the project from my GitHub page:


git clone https://github.com/divyabhushan/my_nav_app.git

Now, let us understand the project directories and files layout, as printed by the command: ls -lTR

Source Code Layout - Git Bisect - Edureka

Next, let us see the project history journal to view the commits I made in order to generate this code-

For instance, a simple git log command prints the history in detail, however, I like to pretty format and customize the history. Thereby, let us set an alias name – ‘hist’ using the git alias command as shown below:

git alias.hist 'log --pretty=format:"%C(yellow)%h%Creset %ad | %C(green)%s%Creset%C(red)%d%Creset %C(blue)[%an]" --graph --decorate --date=short'

Now, I am going to carry out this bug fix feature in a separate branch, so as to not interfere with the main development on the ‘master’ branch. To do that, follow the below set of commands:

  • Create branch ‘dev’: [master] $git branch dev
  • Switch to branch ‘dev’: $git checkout dev
  • List the history logs: [dev] $git hist [Note: ‘alias’ command used here]

Commit History Logs - Git Bisect - Edureka

Further, I have highlighted the last known good commit that I know in which my script worked fine with expected test case results, this commit snapshot is tagged as v1.0.

So, now that we know our last good commit, let us go forward in this article on ‘git bisect’ and test the application.

Test the application

Run the script as – $./scripts/myApplication.sh  [ testing first time ]


First run of failed application - Git Bisect - Edureka
Clearly, my present project state is in error, and I am not sure what change I made in which commit that introduced this change. So, next in this article on git bisect, let us see how to identify the bad commit.

Identification of the bad commit

To begin inspecting for the bad commit, you would follow the below steps:

  • Start the bisect command: git bisect start
  • Mention the bad commit id: git bisect bad HEAD or git bisect c5b3ca8
  • Mention the last-known-good-commit id: git bisect good v1.0 or git bisect 93859d8

    Start Bisection - Git Bisect - Edureka

This bisects the commit history range roughly midway between the good and bad commits that brings us to the commit id: f61a7e8

Bad and the good commit range with first suspected commit - Git Bisect - Edureka

Hence, the command has checked out the project version as it was in this commit id. Now, let us go ahead and test our application again.

Command to run the application: $./scripts/myApplication.sh [ testing second time ]

Checked Out First Revision - Git Bisect - Edureka
Since the application passed in this commit, this commit is certainly ain’t the bad commit. So, next, you have to inform the same to the bisect command as – $git bisect good

Git Bisect Good - Git Bisect - Edureka
Now, this will further narrow down the search result into the first half of the range as shown –

Commits - Git Bisect - Edureka
Test your application again – Command: $./scripts/myApplication.sh [ testing third time ]

Test Application - Git Bisect - Edureka
So, since we see an error as above, this is a bad commit.

Let the bisect command know, run $git bisect bad

Git Bisect Bad - Git Bisect - Edureka
That further narrows down the search and brings you to the last blue encircled middle revision: a6ac769

Middle Version - Git Bisect - Edureka

So, I test my application one last time using the same command: $./scripts/myApplication.sh [ testing fourth time ]

Bad Revision - Git Bisect - Edureka

Now, since the application failed again, it is still a bad commit. So, lets run the following command:

Run the command: git bisect bad

Bad commit found

This concludes the only last commit left which is bad-

culprit commit id
So you know this is where the code broke. What next?

Understand what file had the bug

In this case, the output gives you minimal information about the commit id, author name, and the authored date along with the commit message and the path that was modified.

If you wish to debug further you need to read the commit id object.

Command: git show a6ac76994b3f6c7519204f910fc787b7928cf8ef

This will read the commit object and print the log message and textual diff.

Bugged file - Git Bisect - Edureka

You might as well use the ‘git blame’ command to analyze how and in which commit each line was changed by which author, run the command as: git blame code/develop_nav.sh

Stop the search

To stop the search, use the following command:

Command: git bisect reset

Git Bisect Reset - Git Bisect - Edureka
Thus, the bisection process is stopped and you are back on the branch from which you started the search. Now, the next step is to fix or debug the code.

How to fix/debug the code?

Well, there are a couple of workarounds that you could do to fix the current state of the project now that you have identified the commit that brought the bug in the first place.
However, if you are altering a commit on a shared repository it is best to revert the change using the ‘git revert‘ command.

Task: Revert the changes done by the bad commit mentioned

Command: git revert a6ac769

Revert Bad Commit - Git Bisect - Edureka

Revert a Commit - Git Bisect - Edureka

As a result, reverting the changes made by this commit did 2 things:

  • It deleted the last 3 added lines (indicated in green) and added the deleted line(indicated in red) back. (reverse of a6ac769)
  • Created an extra commit with the revert message information

“Revert command also makes it easier to track the change you reverted from the original commit”

Use the ‘show’ command again to read the object id, like so-

Command: git show 801f029

Show Reverted Commit - Git Bisect - Edureka

Now, go forward and test the application. It will execute properly.

Command: $./scripts/myApplication.sh

Execute The Application - Git Bisect - Edureka

In contrast, if you want to remove the bad commit from history:

  • You could use the ‘git reset‘ command with the “--hard” option(though not recommended in a shared repository).

  • Check out an earlier version of a single file using the ‘git checkout‘ command with the ‘-- <path/filename>‘ option.

It should be noted, this will only make changes in your local repository until you push the changes to a remote repository. Since some changes create new commit object id as in our case above in such cases a normal push to the remote repository is rejected as the history would have diverged. You must use the ‘git push‘ command with the ‘--force‘ option.

Update ‘master’ branch

While I fixed the bug on my ‘dev’ branch, I can now merge this change with the ‘master’ branch also-

  • switch to ‘master’, command: git checkout master
  • pull recent updates from ‘origin/master’ to ‘master’, command: git pull origin
  • merge ‘dev’ changes, command: git merge dev

However, your merge may generate conflicts if there are more commits from the remote repository. Resolve conflicts and continue with the merge.
Finally, push only the stable ‘master’ branch commits to the remote repository while you get your dirty work(bug, features, enhancements) done only on the feature branches such as ‘dev’ in this example.
Moreover, it is best to adopt a logical branching strategy to streamline and secure your git workflow process.

To summarize, ‘git bisect’ is a handy and useful command that quickly identify the commit id that introduced a fault in your running code with the help of an extensive binary search by logically dividing the commit logs halfway between the good and bad commit range. To conclude, you learned to detect the faulty commit and revert the change made by it.

In addition, to the subcommands ‘good’ and ‘bad’ you can also use terms like new and old to describe the revision state. You may run the command a multiple times passing different subcommands and revision/commit ids to identify different commit (she-1) ids. Alternatively, an automated test script may also be run to build the broken code using this command. Also, find a detailed description of this command by running git bisect --help on the terminal. So, folks with this we come to an end to this article on Git Bisect.

The intention of DevOps is to create better-quality software more quickly and with more reliability while inviting greater communication and collaboration between teams. If you are intrigued by this article, check out the DevOps training by Edureka, a trusted online learning company with a network of more than 250,000 satisfied learners spread across the globe. The Edureka DevOps Certification Training course helps learners to understand what is DevOps and gain expertise in various DevOps processes and tools such as Puppet, Jenkins, Nagios, Ansible, Chef, Saltstack and GIT for automating multiple steps in SDLC.

Got a question for us? Please mention it in the comments section of ”Git Bisect” article and we will get back to you ASAP. 

Comments
0 Comments

Join the discussion

Browse Categories

webinar REGISTER FOR FREE WEBINAR
REGISTER NOW
webinar_success Thank you for registering Join Edureka Meetup community for 100+ Free Webinars each month JOIN MEETUP GROUP

Subscribe to our Newsletter, and get personalized recommendations.

image not found!
image not found!

Git bisect: How to identify a bug in your code?

edureka.co