My guide to understanding Git rebase -i

The git rebase command is one of the most powerful in Git. It can rewrite your repository's commit history by rearranging, modifying, and even deleting commits.
6 readers like this
6 readers like this
Why and how to handle exceptions in Python Flask

Image from Unsplash.com, Creative Commons Zero 

Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency. It is an essential tool in an open source developer's toolkit.

This article covers why and how to use the git rebase --interactive (-i for short) command. This is considered an intermediate Git command, but it can be very useful once you start working with large teams.

This command is one of the most powerful in Git. The git rebase command helps you manage multiple commits, including:

  • Flatten (or squash in Git terminology) several commits so that they look like they were all done at once
  • Delete one of the commits
  • Split one commit into two
  • Reorder the commits

Yes, the git rebase command can rewrite your repository's commit history by rearranging, modifying, and even deleting commits. So let's get started!

Helpful instructions in the rebase message

The git rebase -i interface is, as its long form --interactive flag implies, an interactive interface. It provides a list of commits, and then you choose what actions you want Git to take on each of them. Taking no action is a valid choice, but at least one commit must be marked as the one to squash, or the rebase is functionally meaningless.

  • p, pick — Pick this commit to keep.
  • e, edit — Edit this commit to amend the commit message.
  • r, reword — Use this commit, but also edit it.
  • s, squash — Squash this commit into a previous commit. When performing a git rebase -i, you must have at least one commit marked as squash.
  • d, drop — Delete this commit.

Squashing commits

Suppose you have two commits, and you want to squash them into one. This is achieved by using git rebase -i HEAD~2 (that's two commits from your current position) command and by putting the word squash before the commit.

$ git rebase --interactive HEAD~2

Running this command gives you a list of commits in your text editor that looks something like this:

pick 718710d Commit1.
pick d66e267 Commit2.

If you want to make a single commit from two commits, then you have to modify the script to look this:

pick 718710d Commit1.
squash d66e267 Commit2.

Finally, save and exit the editor. After that, Git applies all the changes and opens an editor to merge the two commits:

# This is a combination of 2 commits.
# This is the 1st commit message:

Fuse smoke test versioning.

# This is the commit message #2:

Updated the code.

# Please enter the commit message for your changes.

Saving this results a single commit that introduces the changes of two previous commits.

Reordering commits

Suppose you have three commits, and you want to change their order such that Commit3 is first, Commit2 is second, and then third is Commit1. Run git rebase -i HEAD~3 to make this happen:

$ git rebase --interactive HEAD~3

This script is opened in your editor:

pick 8cfd1c4 Commit1
pick 718710d Commit2
pick d77e267 Commit3

Modify the script like this:

pick d77e267 Commit3
pick 718710d Commit2
pick 8cfd1c4 Commit1

When you save and exit the editor, Git rewinds your branch to the parent of these commits, and applies d77e267, then 718710d, and then 8cfd1c4 as the commit numbers are not matching.

Delete a commit

Suppose you have two commits and want to get rid of the second one. You can delete it using the git rebase -i script.

$ git rebase -i HEAD~2

This script is opened in your editor:

pick 8cfd1c4 Commit1
pick 718710d Commit2

Place the word drop before the commit you want to delete, or you can just delete that line from the rebase script.

pick 8cfd1c4 Commit1
drop 718710d Commit2

Then save and exit the editor. Git applies the changes and deletes that commit.

This can cause merge conflicts if you have many commits later in the sequence that depend on the one you just deleted, so use it carefully. But you have an option to revert the changes.

Rebase with caution

If you get partway through a rebase and decide it's not a good idea, use the git rebase --abort command to revert all the changes you did. If you have finished a rebase and decide it's wrong or not what you want, you can use git reflog to recover an earlier version of your branch.

Rebasing is powerful and can be useful to keep your repo organized and your history clean. Some developers like to rebase the main branch so that the commits tell a clear story of development, while others prefer for all commits to be preserved exactly as they were proposed for merging from other branches. As long as you think through what your repo needs and how a rebase might affect it, the git rebase command and the git rebase -i interface are useful commands.

What to read next
Tags
I am from Bangalore, India and currently working as Associate Software Engineer with Red Hat team, Bangalore, India.

2 Comments

"Some developers like to rebase the main branch" - I think you meant "rebase their development/feature/bugfix branches" or "rebase from the main branch" - you should almost never rebase on your main branch or other branches that are in active use by other developers since it can be highly disruptive due to the loss of connectivity with commit history.

It can be very useful to "clean up" the contents of feature/bugfix branches before merging.

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.