Using an Interactive Rebase to Squash Commits

Chris Wahl · Posted on2015-07-022020-05-08

I’m not a fan of creating commits within Git that just fix a typo. This clutters up the log / history. These sorts of commits can be cleaned up with an interactive rebase or by resetting the HEAD by one commit to remove the typo. In my experience, both of these options are limited to local changes. If other people have pulled your changes, or you have pushed to a remote repo, this gets messy.

Because I was asked to show an interactive rebase, I’ll do so here. Let’s say that I’m working on a PowerCLI script and made a typo. I meant to throw an error message that says VMware.VimAutomation.Core but instead typed VMware.VimAutomation.Vds. This is because I copied the code from another script and didn’t notice the mistake. The error is shown below on line 36 and changes have already been committed.

Using an interactive rebase allows me to alter history. I’m doing this on a local branch called feature1 where I’m working on features for my PowerCLI script. The branch does not exist in any other remote repo. Here’s how the interactive rebase works:

git rebase -i HEAD~2 – Rebase the commits with an -i argument to make it interactive. The HEAD~2 tells Git that I want to rebase using the last two commits.

Once I fire off the interactive rebase command, a notepad will open up with a list of commits covered in HEAD~2 (the last two commits from HEAD). Commits listed here are from oldest to newest, which is in reverse of the log. I’ve changed the commit on line 2 from pick to squash, meaning I want to squash it down into the first commit on the list. Save the file and close the text editor – for those like me that use Notepad++, this means completely closing Notepad++ or else the rebase won’t continue.

Because I’ve asked for a squash, another text editor opens asking which commit message to use. Delete the unwanted message.

There. Now the only lines without a comment refer to the final commit message. Save and quit the text editor.

The status of the rebase is successful and running git log –oneline shows that the typo commit is gone, but the changes have been rolled into the previous commit. Much cleaner.

Using git reset for this example is also fine, but means that I’ll need to go back into the staged changes and fix the typo again before commiting all of the changes to the script. For benign mistakes, you could also use a cherry-pick.