Featured image of post Cleaning Commit History with Interactive Git Rebase Featured image of post Cleaning Commit History with Interactive Git Rebase

Cleaning Commit History with Interactive Git Rebase

Step-by-step guide to squash, edit, and clean your Git commit history using the git rebase -i command before creating pull requests.

Introduction

During daily software development, it is common to end up with a messy commit history full of logs like “WIP,” “fix typo,” or “testing deployment.”

If you merge these commits directly into your main branch, finding where a specific bug was introduced or understanding why a line of code was added becomes extremely difficult.

Git’s interactive rebase (git rebase -i) allows you to clean up your commit history before creating a pull request. You can squash multiple commits into one, edit commit messages, reorder history, or delete redundant changes. This article covers the step-by-step workflow of utilizing interactive rebasing.


1. What is Interactive Rebase?

git rebase -i is a command that opens an interactive editor screen displaying a list of your commits within a specified range. By modifying instructions in this list, Git applies those changes to your branch history sequentially.

Core Usecases

  • Squash: Merge small, intermediary commits (e.g., “typo fix”) into a single, clean commit.
  • Reword: Modify commit messages to match team naming conventions.
  • Drop: Completely delete unnecessary commits from history.
  • Edit: Pause the rebase process at a specific commit to add or remove files.

2. Basic Step-by-Step Workflow

Let’s look at how to run a rebase to clean up your local branch.

Step 1: Specify the Rebase Range

If you want to edit the last three commits on your current branch, run:

git rebase -i HEAD~3

To edit all commits since your branch diverged from another branch (e.g., main), run:

git rebase -i main

Step 2: Configure the Todo List

Running the command opens your system’s default text editor (e.g., Vim, Nano, or VS Code) displaying a list of commits:

pick a1b2c3d WIP: Started login interface
pick e5f6g7h fixed typo in input
pick i9j0k1l Added login validation

# Rebase a1b2c3d..i9j0k1l onto z9y8x7w
# ...
  • Note: The commits are displayed in chronological order: oldest at the top, newest at the bottom.
  • Change the keyword at the start of each line to tell Git how to handle that specific commit.

Core Action Commands

CommandAbbreviationAction
pickpUse the commit as-is (default).
rewordrUse the commit, but edit the commit message.
editeUse the commit, but pause the rebase to edit files.
squashsMerge this commit into the previous (older) commit and combine messages.
fixupfMerge this commit into the previous commit, discarding this commit’s message.
dropdCompletely remove this commit.

Practical Example

To merge the typo fix and validation commit into the initial “Started login interface” commit, edit the file as follows:

pick a1b2c3d WIP: Started login interface
f e5f6g7h
s i9j0k1l
  • e5f6g7h is set to fixup (f), meaning it merges into a1b2c3d and its message is discarded.
  • i9j0k1l is set to squash (s), merging into the parent while prompting you to rewrite the final combined commit message.

Save and close the editor to begin the rebase.

Step 3: Write the Final Commit Message

If you selected squash, Git opens another editor screen to finalize the combined message:

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

WIP: Started login interface

# This is the commit message #2:

Added login validation

Rewrite this into a clean commit message:

feat: Implement login page with validation rules

- Designed form fields for email and passwords.
- Added client-side red border indicators on input validation errors.

Save and close the editor. Git will apply the changes, squashing the three commits into a single node.


3. Resolving Conflicts During Rebase

If a conflict occurs, Git pauses the rebase and highlights the conflicting lines.

  1. Resolve conflicts manually: Edit the conflicting source code files to choose the correct changes.
  2. Stage the changes: Run git add <filename> (do not run git commit).
  3. Continue the rebase: Run:
    git rebase --continue
    

If you get stuck or make a mistake, abort the entire process and return your branch to its pre-rebase state by running:

git rebase --abort

4. The Golden Rule of Rebasing

While rebase is incredibly useful, you must follow one strict guideline:

⚠️ Warning

Never rebase commits that have already been pushed to a public/shared repository branch (e.g., main or develop) where other developers are working.

Rebasing changes commit hashes. If you push modified hashes to a shared branch, it breaks other developers’ local history tracking, leading to merge conflicts and potential code loss. Only rebase local commits or commits on your isolated pull request branch.

Conclusion

Using git rebase -i lets you save your work in progress as small local commits, then tidy them up into a clean feature commit before sharing your code with the team. Start using interactive rebase to keep your repository history readable.