Git rebase -i belong to us

git rebase -i is an *easy* way to squash many commits into one, so your commit log will be nice and pretty.

The Basics

1. Why you need git rebase -i

Once you’re done working on your feature branch, you are ready to merge it to master and push. After you rebase your branch over master your commit log should look something like this:

All of your feature branch’s commits

Master’s commits on bottom, followed by all of our feature_branch’s commits. This is kind of an ugly commit log. More than ugly — it is harmful, as it is difficult to understand the essence of the changes applied, which is what a commit log is essentially for.

Especially when working in a large team, people other than yourself will see and try to understand your code changes. A ‘git blame’ run a day or a year from now will benefit immensely if the commit message attached to the change explains the reason for which that change was introduced.

It would be much better if we could squash all of our commits into one single commit saying something like ‘ADDED OUR FEATURE’. That way anybody looking at the commit log, or using git history in the future to see why we added any one of our changes, will immediately understand.

Logically, we want to add only one single commit message to the repo’s history (or at most, just a few).

2. How to use git rebase -i

After rebasing your branch over master, run your favorite version of ‘git log’ to see how many of your commits you’re going to ‘squash’ together. In our case above, we can see it’s 11 messages. So:

$ git rebase -i HEAD~11

This will open up your git-configured text editor (Vim, by default) with a list of the commit messages (in reverse order, so oldest is on top):

rebase -i’s list of commit messages, to be re-applied “interactively”

Now what we want to do is squash them together. Basically in our case we only want to use the top commit (‘ADDING COOL FEATURE’) and discard the other commit messages. We do this by telling git to ‘fixup’ every commit line except the first one. To ‘fixup’ means “meld into previous commit, and discard this commit’s log message”. We leave the first commit with ‘pick’, because we *do* want to use its message.

:wq (write-and-quit Vim), and now git ‘fix-up’s per our instructions. The end result is the following log:

We now have the sames changes as before, but encapsulated into a single commit message. Much cleaner and easier to show and understand.

If we want to change that commit’s message (for a final, clean merge to master with one carefully-crafted commit message), we could once again:

$ git rebase -i HEAD~1 

This time we only need commit back. And we change ‘pick’ to ‘r’ for ‘reword’, then change the commit message and save.

Now that’s a nice, clean commit log. Wasn’t that easy?

Thanks for reading! Comments will be appreciated at sella.rafaeli@gmail.com.