Git Interactive Rebase Tutorial: Step-by-Step Guide

Mae Capozzi · January 6, 2020Learn how to use git rebase interactive to clean up messy commit history, squash commits, and rewrite messages before merging your branch

In this post, I'm using vim. But you can use a different editor if you want! You'll need to figure out how to use your editor as your machine's default git commit/diff tool. You can find instructions for configuring this with VS Code here.

Developers have different opinions about whether to rebase or not. Some feel strongly about not modifying commit history, even if the commit log looks something like this:


I'd prefer it if my teammates didn't see all of my embarrassing commit messages, I want to make sure that my commits are meaningful and will help my teammates later, and I also want to regularly commit without interrupting my flow. For that reason, I like amending my history before I push my branch up to Github.

This allows me to write clear, detailed commits like this one, even though my commit log looks like the one above most of the time:


One way to amend that history while keeping your branch up to date with master is to use an interactive git rebase.

This is my usual workflow:

  1. Checkout the master branch and pull down any new changes

  1. Checkout your branch again. Pro tip: running git checkout - will bring you back to the branch you were on previously.

  1. Rebase against the master branch to pull any of the new changes from master onto your branch. You may run into merge conflicts at this point. You'll need to resolve them before moving on.

  1. Run the interactive rebase command

If you have two commits on your branch, you'll see something that looks like this:


At the end of the interactive rebase, you want a single commit with a clear message, written in present tense.

  1. Because we want to reword the first commit, change the first line from pick to reword.

  2. We want to squash the second commit into the first, so we'll change the second commit to squash or fixup.

There's a slight difference between squash and fixup. squash merges the previous and current commit, but keeps the message. fixup merges the previous and current commit, and discards the message. I tend to use squash because I often like to keep track of that message for when I reword my commit.


When you close this window, a new window will open that looks like this:

Add blog post

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Mon Jan 6 16:18:52 2020 -0500
#
# interactive rebase in progress; onto 795b95f
# Last command done (1 command done):
#    reword cca9f22 Add blog post
# Next command to do (1 remaining command):
#    squash 53a5620 Work on blog
# You are currently editing a commit while rebasing branch 'rebase-example' on '795b95f'.
#
# Changes to be committed:
#       new file:   content/blog/how-to-rebase/index.md
#
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
"~/Desktop/Codes/blog/.git/COMMIT_EDITMSG" 17L, 564C
  1. Delete the commit message and replace it with something more meaningful.
Add a blog post on how to interactive rebase

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Mon Jan 6 16:18:52 2020 -0500
#
# interactive rebase in progress; onto 795b95f
# Last command done (1 command done):
#    reword cca9f22 Add blog post
# Next command to do (1 remaining command):
#    squash 53a5620 Work on blog
# You are currently editing a commit while rebasing branch 'rebase-example' on '795b95f'.
#
# Changes to be committed:
#       new file:   content/blog/how-to-rebase/index.md
#
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
"~/Desktop/Codes/blog/.git/COMMIT_EDITMSG" 17L, 564C

When you close this window, you'll see another one pop open that looks like this:


  1. You can delete everything besides the message you want to keep:

If it worked, you'll see a message like this: Successfully rebased and updated refs/heads/rebase-example.

If you run git log, you should only have a single commit with your new message.

Now, if you want to push your code up to Github and haven't pushed any commits up yet, it's as simple as just running git push. If you or someone else has already committed, and you want to override that history, you'll need to force push. I'd recommend running git push --force-with-lease instead of git push --force. --force-with-lease will make sure that you don't accidentally overwrite your teammate's code. (You'd better believe I learned that the hard way!)

As always, before you start rebasing with abandon confirm that your teammates are on board. You want to make sure that you're following your team's etiquette and staying consistent.

Continue Reading

aiobservabilitydeveloper-tools

AI agents removed the friction from writing telemetry

I used to avoid adding telemetry because it felt like tedious busywork. Now with Claude handling the OpenTelemetry boilerplate, I'm instrumenting everything.

Read Post