Professional Version Control with Git: Pt 3 – Rebase and Bisect
Tags: bisect, git, rebase
Published: 2021-07-10 19:39:18

---
title: Professional Version Control with Git: Pt 3 – Rebase and Bisect 
published: true
description: Hello everyone and welcome to part 3 of the professional Git series here at Erik&#8217;s Code Space. In part 1, we learned the basics and [&#8230;]
tags: bisect, git, rebase
canonical_url: https://erikscode.space/index.php/2021/04/16/professional-version-control-with-git-pt-3-rebase-and-bisect/
cover_image: https://i1.wp.com/erikscode.space/wp-content/uploads/2021/04/pexels-rodnae-productions-6069605-scaled.jpg?fit=2560%2C1707&ssl=1
---

[Part 1 - The Basics](https://dev.to/erikwhiting88/professional-version-control-with-git-pt-1-the-basics-3ahm)
[Part 2 - Collaboration](https://dev.to/erikwhiting88/professional-version-control-with-git-pt-2-collaboration-26mp)

Hello everyone and welcome to part 3 of the professional Git series here at Erik’s Code Space. In [part 1](https://erikscode.space/index.php/2021/03/26/professional-version-control-with-git-pt-1-the-basics/), we learned the basics and got our skills good enough to start version controlling our own projects. In [part 2](https://erikscode.space/index.php/2021/04/05/professional-version-control-with-git-pt-2-collaboration/), we learned about the collaboration tools available in git and got our skills good enough to start contributing to open source projects. In this part, we’re going to learn about the rebase and bisect commands, two commands that help us with troubleshooting. Without further ado, let’s begin.

Keeping History Clean
---------------------

In part 1, we learned about how our commit messages become the official “history” of our projects. The git history is supposed to keep a timeline-like record of the growth and change of our repository, so we try to keep our commit messages accurate and helpful, so then when someone runs a `git log` command against our repo, they get an accurate idea of how the project has been evolving lately.

Sometimes though, we need to rewrite history, or get rid of it completely. Maybe we made a bad commit, made a typo in our commit message, or need to combine two commits into one. That’s where `git rebase` comes in! Let’s get started; make a directory called `rebase_and_bisect`, `cd` into it, and run the `git init` command. If you’re using a Linux or Mac terminal, or GitBash for Windows, the following commands will do this:

```
$> mkdir rebase_and_bisect
$> cd rebase_and_bisect
$> git init
```


Now make a file called `poem.txt` and commit it to the repository:

```
$> touch poem.txt
$> git add .
$> git commit -m "Create file"
```


Now we’ll populate that file with a beautiful poem I’ve written. We will add one line at a time and commit that changes before writing the next line. I will share the commands to do this below, without the command prompt (the `$>`) so that you can copy and paste them into your terminal, saving you some time. (Please note, the following commands will probably not work with PowerShell or CMD, please use GitBash if you’re on Windows):

```
echo "Roses are red" > poem.txt
git commit -am "Add first line"
echo "JavaScript is yellow" >> poem.txt
git commit -am "Add second line"
echo "I'm learning git" >> poem.txt
git commit -am "Add third line"
echo "and I wanna say hello!" >> poem.txt
git commit -am "Add fourth line"
```


You might have to manually press “enter” one more time, but you should now have a four line poem in `poem.txt`.

There’s one more piece of housekeeping we have to do before we get on with the rest of this tutorial, setting up our git editor. The git editor is the text processing program that opens when you do things with git that require editing text. I believe the default text editor on GitBash is vim, which isn’t user friendly. Personally, I like nano, so in order to set my default git text editor to nano, I would run the following script:

```
$> git config --global core.editor "nano -w"
```


If you want to use a different program, you have to pass the path to that program in place of where I put `nano -w`. For a more exhaustive list of how to set specific text editors, click [this](https://www.git-scm.com/book/tr/v2/Appendix-C%3A-Git-Commands-Setup-and-Config?fbclid=IwAR0pC9Cf4DO8dWPzYQCaxb9qKONlCJW0nPg8XH7IO5cuj2-hcqKuprzwgmY) link.

With this out of the way, let’s learn about `rebase`.

Rebase
------

We learned in part 1 that commit messages make up the history of our project. When someone runs `git log`, they see all the commit messages made on the project. Our goal is to write concise yet descriptive messages of the work we’ve done so that the collection of commit messages show an accurate picture of where our project came from and how it’s evolving.

Sometimes though, we make mistakes with our commit messages. We could make a typo, duplicate commits, or commit something we really didn’t mean to. Once we’ve made the commit though, the damage is already done, right? Wrong! With `git rebase`, we can rewrite history!

### Making Bad Commit Messages

One of the main uses of using `git rebase` is rewriting commit messages. We’ll open up `poem.txt` in our text editor of choice and sign our name at the bottom. Then we’ll commit the changes but, oh no! We make a typo:

```
$> git commit -am "Signing my nammee"
```


Run `git log` to see the typo in our list of otherwise good commit messages. We’re now going to use `rebase` to fix this. We’re going to use the *interactive* version of rebase to do this, and we’re going to *go back one commit* when rebasing. So the command I want you to run is:

```
$> git rebase <strong>-i</strong> HEAD<strong>~1</strong>
```


The `-i` is for “interactive” and the `HEAD~1` means “go back one commit from the latest version.” As soon as you hit enter, you should see something like this:

![](https://i1.wp.com/erikscode.space/wp-content/uploads/2021/04/image-7.png?resize=601%2C397&ssl=1)Let’s talk about what we’re looking at real quick. This text file is called `git-rebase-todo` and lives inside the local `.git` directory for this project. The first line is the commit we’ve rolled back to, the one with the typo. Below that is a few lines to help users figure out what to do from here, and is pretty helpful once you get the hang of rebasing. For now though, I’ll just walk you through the next few steps.

So the goal here is to fix the typo from our last commit message. That means that we want to “reword” the commit message, so on the first line, delete `pick` and type `reword`. Then, save the file and exit it (if you’re using nano, you save by pressing “Ctrl + o” then press enter and exit with “Ctrl + x”).

Once you’ve closed the file, another one will open containing the commit message for that particular commit. Mine looks like this:

![](https://i1.wp.com/erikscode.space/wp-content/uploads/2021/04/image-8.png?resize=674%2C300&ssl=1)Scroll over to `nammee` and change it to `name`, save, and exit. You’ll be returned to the terminal with a message about successfully rebasing. Run `git log` again and what do you notice? The typo from our last commit message is gone and our history is saved! Here’s what mine looks like:

![](https://i1.wp.com/erikscode.space/wp-content/uploads/2021/04/image-9.png?resize=626%2C538&ssl=1)#### Did you get Stuck in Vim?

If you missed the part about setting your default text editor and your files opened in a text editor that doesn’t seem to make sense, you might be in vim. Don’t panic, I’ll walk you through getting out of this. First, check and see that you really are in vim. If you are, you’ll notice that all the lines below the commented-out portion (the portion preceded by `#`s) are all tildes (`~`). In my GitBash, vim looks like this:

![](https://i2.wp.com/erikscode.space/wp-content/uploads/2021/04/vimtildes.png?resize=582%2C506&ssl=1)Operating vim is a little weird if you’re not used to it. When it first opens, you’re in “normal” mode and you can’t edit text the way you think you can. To enter “insert” mode, just type the letter `i`. Once you’ve done this, you can edit the text like you would in a normal program, using the arrows to maneuver around and the backspace and delete buttons the way you’d expect.

Once you’ve changed “pick” to “reword,” you have to go back into “normal” mode by pressing the `Esc` key. Once you’ve done this, you can save the file by first pressing the key combination for colon (`:`) which is Shift + ;. You’ll notice now that your cursor is now at the bottom left of the screen. Type `wq!` and then press enter. This is the command for saving and exiting (or **w**riting and **q**uitting). Repeat the process when it opens the commit message file and you should be good to go!

### Consolidate Commits

Sometimes, I forget to do a whole task before I commit it. As an example, say I wanted to remove my name from `poem.txt` file. I open it up, delete my name, save, the file, then run:

```
$> git commit -am "Removed name"
```


But then I realize that I didn’t also delete the empty line my name was on. So I go in and delete that line, which was really part of the name-deleting work so I make a silly commit message like:

```
$> git commit -am "Finish removing name"
```


Now my history looks a little weird because I have two commits for deleting my name. There’s nothing really wrong with this except that I want my git history to be clean. In order to do that, I decide I want to put the last two commits together. So I need to do another interactive `rebase`, this time going back ***two*** commits, so I run:

```
$> git rebase -i HEAD~2
```


This time, when the `git-rebase-todo` file opens, I have the last two commits listed. This means I want to ***squash*** the most recent commit into the last one, so I change `pick` to `squash` on the second line:

![](https://i1.wp.com/erikscode.space/wp-content/uploads/2021/04/image-11.png?resize=638%2C155&ssl=1)On the next screen, I will pick the commit message I want to keep. I’m going to remove the `Finish removing name` message by commenting it out, the file will look like this:

![](https://i2.wp.com/erikscode.space/wp-content/uploads/2021/04/image-12.png?resize=587%2C380&ssl=1)Notice that I added the `#` symbol in front of the line underlined in red. From here, save and exit this file again to return to the terminal. Run `git log` once again and what do you notice? We’ve successfully merged the last two commits into a single commit, keeping our history clean!

There’s a ton more you can do with `rebase` and I encourage you to read the commented lines detailing the commands in the `git-rebase-todo` file. Play around with it some to get a feel for what you can do with this useful tool.

Bisect
------

Git’s `bisect` command is pretty cool because it helps us locate the source of a bug by searching for the specific commit a bug was introduced. The way it works is we first identify a “bad” commit, or a commit in which a bug exists, then we identify a commit in which the bug does not exist, or a “good” commit. Then, git will checkout old commits between the good and bad ones and ask us if the bug still exists.

Then, by process of elimination, we eventually pinpoint the exact commit that broke introduced the problem. It might sound confusing, so let’s just get hands on with it. I’m going to give you another list of terminal commands to run. One of which will intentionally introduce a bug, which we’ll then pinpoint with the `bisect` tool. Run the following commands:

```
echo "This poem is about JavaScript" >> poem.txt
git commit -am "Add description of poem"
sed -i -e 's/yellow/orange/g' poem.txt
git commit -am "Replace 'yellow' with 'orange'"
echo "This is for my git tutorial" >> poem.txt
git commit -am "Add reason for poem"
```


Now, take a look at the contents of `poem.txt` and note the bug, “yellow” seems to have been replaced with “orange.” See for yourself:

```
$> cat poem.txt
Roses are red
JavaScript is <strong>orange</strong>
I'm learning git
and I wanna say hello!
This poem is about JavaScript
This is for my git tutorial

```


We’re now going to use `bisect` to identify the commit that introduced this bug. The first thing we have to do is identify a good commit–where the bug doesn’t exist–and a bad commit–where the bug does exist. Run `git log` to find these commits. Please note that your commit hashes will not match mine, so for the rest of the article, you cannot copy/paste my example commands, you’ll have to use your relevant commit hashes.

My git log looks like this:

![](https://i1.wp.com/erikscode.space/wp-content/uploads/2021/04/image-13.png?resize=487%2C654&ssl=1)Since I know that the bug currently exists, I’m going to call my most recent commit (`b33c81d`) the bad one, and I know that the second line still said “yellow” when I signed my name, so I’m going to call that commit (`00b7e71`) the good one.

Now, I need to `start` the bisect wizard by running `git bisect start`, then identify the good and bad commits with `git bisect good [hash]` and `git bisect bad [hash]`. Take a look:

![](https://i0.wp.com/erikscode.space/wp-content/uploads/2021/04/image-14.png?resize=800%2C191&ssl=1)Git then picks a commit between the good and bad ones. From here, we’re supposed to check and see if the bug still exists, if it does, we tell it with `bad` if not, we use `good`. So check the file for the bug:

```
$> cat poem.txt
Roses are red
JavaScript is yellow
I'm learning git
and I wanna say hello!
This poem is about JavaScript
```


The word “yellow” is still there, so we run `git bisect good`. Git then picks another commit between this one and the commit we marked as bad. Take a look:

![](https://i2.wp.com/erikscode.space/wp-content/uploads/2021/04/image-15.png?resize=760%2C183&ssl=1)When we check the contents of the `poem.txt` file, we see that we called JavaScript “orange” instead of “yellow.” So we mark this one as bad with `git bisect bad`. With this information, git now believes it’s found the commit that introduced the bug. It correctly identifies the commit in which we replaced “yellow” with “orange” (for me, commit `d5ebcc3`) as the offending commit.

We’ll now exit the bisect wizard by running `git bisect reset` which returns us back to the most recent commit. Now that we know which commit introduced the “yellow -> orange” bug, we’ll use `rebase` to get rid of it.

### Using Rebase to Fix Bug

Since we know the commit that introduced the bug, we should check and see what was going on with that commit. We can compare the commit with it’s previous commit to see what changes were made by using the `git diff` command and passing in two hashes.

For me, the hash for the bad commit was `d5ebcc3`. If I want to reference the commit before that without looking up its hash, I can append `~1` to the hash as something of a relative way of referencing the previous commit. In other words, if I want to compare `d5ebcc3` and the commit prior to it with `diff`, I would run the following command:

```
$> git diff d5ebcc3<strong>~1</strong> d5ebcc3
```


The output then shows me what changed in that commit, see my screenshot:

![](https://i2.wp.com/erikscode.space/wp-content/uploads/2021/04/image-16.png?resize=613%2C239&ssl=1)Since I can see from this diff that nothing other than changing the word “yellow” to “orange” happened in this commit, I can safely assume that the whole commit can be removed from the project’s git history. I will use rebase to expunge any record of that commit ever taking place. To do this, I need to do another interactive rebase, this time to the commit before `d5ebcc3`. In order to this, I run the following command:

```
$> git rebase -i d5ebcc3~1
```


This brings us back to `git-rebase-todo` file we saw earlier. This time, I’m going to `drop` the offending commit. Not only will that remove that commit’s message from the project’s history, it’ll also get rid of the changes made in that commit. Make your file look like mine (but don’t change the commit hashes):

![](https://i2.wp.com/erikscode.space/wp-content/uploads/2021/04/image-18.png?resize=602%2C225&ssl=1)Save and exit the file and you’ll be returned to the terminal with the message “Successfully rebased and updated refs/heads/main.” First, let’s make sure the bug is fixed. `cat` the contents of `poem.txt` and make sure JavaScript is yellow again:

```
$> cat poem.txt
Roses are red
JavaScript is yellow
I'm learning git
and I wanna say hello!
This poem is about JavaScript
This is for my git tutorial

```


Great! The bug has been fixed, now run `git log` and note that the offending commit has been stricken from the record:

![](https://i1.wp.com/erikscode.space/wp-content/uploads/2021/04/after_rebase.png?resize=800%2C724&ssl=1)And now we know how to use `bisect` to locate bugs and `rebase` to get rid of them!

Conclusion
----------

That concludes part 3 of the Professional Version Control with Git series. In part 1, we learned the basics of using git for our own projects, then in part 2 we learned about the tools for collaboration. Finally, in this part, we learned how to use `rebase` to keep our history clean, and `bisect` to help us track down bugs. That concludes the Professional Version Control with Git series, but keep an eye out for more content about version control and collaboration tools. Don’t hesitate to contact me with any questions you have by emailing ewhiting@erikscode.space or hitting me up on Twitter, [@ErikWhiting4](https://twitter.com/ErikWhiting4). Thanks, and see you next time!