Cleaning Local Git History with Interactive Rebase
Learn how to use git rebase -i to squash WIP commits, rewrite messages, and clean up your local history before merging into a shared main branch.
30 Mar 2026, 20:16 UTC

The Problem: Messy Local Commit Histories
During active development, it is common to create "work-in-progress" (WIP) commits, such as "fixed typo," "trying again," or "temp save." While these are helpful for local checkpoints, merging them into a shared main branch litters the project history with noise, making it difficult for reviewers to understand the actual intent of a feature or bug fix.
The solution is git rebase -i (interactive rebase). This tool allows you to rewrite your local commit history—combining small changes into logical units and refining messages—before the code ever reaches a shared remote.
Prerequisites
- A local feature branch containing commits that have not been pushed to a shared remote.
- A configured text editor (e.g., Vim, Nano, VS Code) set as your
core.editor. - Basic familiarity with the
git logcommand.
The Interactive Rebase Procedure
To begin cleaning your history, you must identify how far back you want to go. If you want to modify the last four commits on your current branch, run the following command from your terminal:
git rebase -i HEAD~4
Git will open your editor with a list of commits, oldest at the top and newest at the bottom. Each line begins with the word pick. To modify the history, replace pick with one of the following commands:
| Command | Action | Use Case |
|---|---|---|
reword |
Keep the commit, but change the message. | Correcting a typo in a commit message. |
squash |
Combine this commit into the previous one and merge messages. | Merging a fix into the original feature commit. |
fixup |
Combine this commit into the previous one, discarding this message. | Removing "WIP" or "typo" messages entirely. |
drop |
Remove the commit entirely. | Deleting a change that is no longer needed. |
Example Configuration: Cleaning a Feature Branch
Imagine your git log --oneline looks like this:
a1b2c3d Fix login bug
e4f5g6h Fix typo in login
i7j8k9l Add logging to login
m0n1o2p Fix typo in logging
To consolidate these into a single, clean commit, your rebase editor should be modified to:
pick a1b2c3d Fix login bug
squash e4f5g6h Fix typo in login
squash i7j8k9l Add logging to login
fixup m0n1o2p Fix typo in logging
After saving and closing the editor, Git will prompt you to write a final combined commit message for the squashed commits. Once finished, the four commits are replaced by a single new commit object.
Verification and Safety Checks
Because rebasing rewrites history (creating new commit hashes), you must verify the result before pushing.
- Verify History: Run
git log --oneline. The commit count should match your intended structure, and the messages should be clean. - Verify Code State: Run
git diff main(or your target branch). The diff should be identical to what it was before the rebase; only the history should have changed, not the code. - Check Reflog: If you make a mistake during the rebase, use
git reflogto find the SHA of your branch head immediately before the rebase started.
Recovery: Rolling Back a Rebase
If the rebase results in unexpected code loss or excessive conflicts, you can reset your branch to its pre-rebase state. Find the commit hash from the reflog (e.g., HEAD@{5}) and run:
# Run on the local branch you are cleaning
git reset --hard HEAD<@{n}>
Risk Warning: --hard will discard any uncommitted changes in your working directory. Ensure your workspace is clean before executing.
Critical Limitations
- Shared Branches: Never perform an interactive rebase on commits that have been pushed to a shared branch. Doing so forces other developers to manually reconcile their history, often leading to duplicate commits and merge conflicts.
- Force Pushing: If you have already pushed your feature branch to a remote (e.g., for a Pull Request), you will need to use
git push --force-with-lease. This is safer than--forcebecause it prevents overwriting work if a teammate has added commits to that remote branch.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.