git rebase -i

Matej Lednicky
4 min readJun 7, 2021

Git. Whenever I explain it to someone, I remember this xkcd comic:

If that doesn’t fix it, git.txt contains the phone number of a friend of mine who understands git. Just wait through a few minutes of ‘It’s really pretty simple, just think of branches as…’ and eventually you’ll learn the commands that will fix everything. (https://xkcd.com/1597/)

I used to think of myself as Cueball from the comic (stick figure on the left). But as years pass I feel like I am becoming the person on the phone 🤓 And maybe thats the reason I am writing about git rebase -i, or interactive rebase.

I will not explain git here. There are many other and better sources for that, for example Git Handbook from Github or list of handy commands for when you fuck up 💩 From this point forward I assume you know git basics.

What is rebase and why should I care?

I am working on a feature. Big deal, everyone is. However I am not the only one working in the repository and someone merges their stuff into main branch before I do. Now I am stuck with this:

Working on my feature in a branch…

Yes, I can git merge main into my feature branch when it has new changes and before I know it my git history is going to look like this:

…and suddenly my git is mess 😡

Once my feature branch is merged into main like this, my team i̶s̶ ̶g̶o̶i̶n̶g̶ ̶t̶o̶ ̶l̶o̶v̶e̶ ̶m̶e̶ will have hard time looking through git history. Single feature is split into multiple commits. In a few weeks no one will care if I had to fix stuff in my feature 10 times and created another commit just to fix a typo.

Instead of merge, let’s git rebase main from my feature branch:

There, much nicer! 🚀

When there are more changes in main I will rebase again:

git rebase main

What about interactive rebase?

Until now I used standard rebase. Interactive rebase has the power to change the history. When I am done working on my cool new feature I will squash all my commits into one and give it a nice descriptive commit message:

git rebase -i master

An editor, in my case vim, is opened and I see a list of my commits:

pick ac5bf36 my feature, work in progress
pick 0524396 my feature, more work
pick f5755c8 my feature, add tests and fix bugs
# Rebase 67d28c6..f5755c8 onto 67d28c6 (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label

I want to squash all commits into the first one (f, short for fixup command — squash and discard commit message because I don’t care about those) and update message of the first commit (r, short for reword command):

r ac5bf36 my feature, work in progress
f 0524396 my feature, more work
f f5755c8 my feature, add tests and fix bugs

Now I can :wq to save and close. Another vim is opened and I can update the commit message (thanks to the reword command) to make sense when someone finds it in a few weeks (eg. add a ticket number). So my team mates can focus all their hate at my code and not my commit message 🤣

After merging my feature branch into main, git history in my repo will look something like this:

Nice and clean git history

Rebase your commits and your team will thank you 🚀

Note: Yes, you can rebase when merging pull request on Github. It does the job, but if you do this locally your reviewers will see single commit with proper commit message which is nice. And you will not forget to update the commit message at merge time. Also, the squashed commit will be authored by you and not by the person who clicked the button on Github.

--

--