In a nutshell
git bisect startgit bisect badgit bisect checkout last_known_good_commitgit bisect good# keep running git bisect good|bad until you find the commit that introduced the bug# alternatively, find the commit automatically
git bisect run <command-that-checks-if-commit-is-good-or-bad>
Intro
git-bisect
is an amazing tool that can help you find a specific change or commit.
Whether you are trying to find a commit that indroduced a bug, a broken CSS style or an upgrade of a third-party library git-bisect
is a powerful tool to assist you in finding it.
The power of
git-bisect
comes from a binary search algorithm which can process massive ammounts of commits in very few iterations.
Practice
In this practice, you suspect that a bug was introduced when you upgraded React to version 16 and you want to find this commit.
Most likely you can just run git-log
on the package.json
and scan through commits, but in your scenario package.json
has dozens of commits and it would take a long time to find the commit.
Also, you love to automate things and be efficient so why not use git-bisect
?
Prerequisites
bash
git
yarn
grep
For practice purposes, let’s create a sample Git repo and Yarn package.
# all commands are executed in bash terminal$ mkdir git-bisect-practice && cd git-bisect-practice$ yarn init --yes$ git init$ echo "node_modules" >> .gitignore$ git add .$ git commit -am "Initial commit"
Now that you have our initial Repo let’s create a few dummy commits to simulate a repository under heavy development.
To create a dummy commit you will run yarn version
in a loop, which creates a git commit if called inside a git repository.
$ N=10 # Number of dummy commits to create$ for i in {1..$N}; do yarn version --minor; done
Now you will install React version 16.
$ yarn add react@^16$ git commit -am "Install React v16"$ git tag reactV16 # tag it for easy navigation later on
Simulate more heavy development by creating more dummy commits.
$ for i in {1..$N}; do yarn version --minor; done
Upgrade React to version 17.
$ yarn upgrade react@^17
$ git commit -am "Upgrade React v17"
Simulate more heavy development
$ for i in {1..$N}; do yarn version --minor; done
Now stop for a moment and look back.
You have a repository with at least a number of 3N commits. On N-commit, you installed React version 16. On 2N-commit you upgraded React to version 17. Now you find ourselves on 3N-commit and you realize that a bug was introduced when you upgraded to React version 17. How can you find that commit?
There are different ways of finding the commit which has React version upgrade but you are here to practice git-bisect
, so dive in.
# Start bisecting
$ git bisect start# Mark current commit as having a new change
$ git bisect new # alternatively - `git bisect bad`# Checkout a known commit that has an old version of React v16
$ git checkout reactV16# Mark that commit as old
$ git bisect old # alternatively - `git bisect good`
These are the required arrangements forgit-bisect
to launch the search.
Now you have two ways to tell git-bisect
to hunt down the commit you need.
The manual way. You mark a commit good or bad depending on which React version is installed. Every time you mark a commit, git-bisect
checks out a new commit picked up using the binary-search algorithm.
First, you want to write a command that will detect if React version is 16 or 17. The utilitygrep
is well suited for that purpose.
$ grep '"react":\s*"\^16' package.json
This command will determine if the current commit contains React version 16.
It would look like so:
# Step 1
$ grep '"react":\s*"\^16' package.json# Step 2
# If React version 16 is installed, run
$ git bisect good # git-bisect checks out the next commit# Otherwise, run
$ git bisect bad # git-bisect checks out the next commit# Step 3
# Go to Step 1
But doing things manually could be time-consuming. You could speed up the search with the help of git-bisect run
.
The fast way. You can call git bisect run
, with the grep
command from the previous step. That will trigger the manual work from the previous section for you.
# Automate search by using `bisect run`
$ git bisect run grep '"react":\s*"\^16' package.json
If everything worked well, you will see an output with the commit that Upgraded React to version 17.
Lastly, remember to reset the state of your git repository:
$ git bisect reset
And this is it. Congrats, hopefully, now you have a new tool under your belt, and it will help you hunt down bugs faster and easier.