Git Interactive Rebase: How to Clean Up Your Local History
Master git interactive rebase to clean up your commit history before pushing. Learn how to squash, reorder, and fixup commits for a professional workflow.
Last Friday, I found myself staring at a pull request with 14 commits. Most of them were titled "fix typo," "oops," or "trying again." I knew that if I pushed that mess to our main branch, my team lead would have a field day. That’s when I turned to git interactive rebase to reshape my local history into something readable.
If you’ve ever felt embarrassed by your "work in progress" commits, you aren't alone. Cleaning up before you open a PR isn't just about vanity; it’s about making life easier for the person who has to review your code.
Why Git Interactive Rebase Matters
When you’re deep in the flow of coding, you commit often to save your progress. That’s a good practice, but those micro-commits rarely provide value to the long-term repository history. By using a rebase, you transform a chaotic sequence of changes into a logical narrative.
Before we dive in, ensure your environment setup is configured correctly, especially your core.editor setting, as you’ll be spending a lot of time in your terminal text editor.
The Basics of Git Commit Squashing
The most common operation I perform is git commit squashing. This process collapses multiple commits into one, allowing you to combine your "fix typo" commits into the main feature commit they belong to.
To start, run:
Bashgit rebase -i HEAD~n
Replace n with the number of commits you want to review. Your editor will open a list of commits that looks like this:
TEXTpick a1b2c3d Add user authentication pick e4f5g6h Fix typo in login pick i7j8k9l Update README
To squash the typo into the authentication commit, change pick to squash (or just s) for the second line:
TEXTpick a1b2c3d Add user authentication squash e4f5g6h Fix typo in login pick i7j8k9l Update README
Save and close the file. Git will then prompt you to combine the commit messages. It’s that simple.
Advanced Cleanup: Using Git Fixup Commits
While squashing is great, I often find git fixup commits even more efficient. If you know you want to merge a commit into a previous one without keeping its message, use the fixup (or f) command.
I typically use this workflow during development:
- Make a change.
- Commit with a temporary message:
git commit -m "fixup". - When I'm ready to clean up, I run the interactive rebase.
- I mark those "fixup" commits as
fin the rebase list.
This saves me the time of manually rewriting commit messages during the rebase process. It’s a huge time-saver when you have a dozen small tweaks.
Comparison of Rebase Commands
| Command | Action | Best Used For |
|---|---|---|
pick | Keeps the commit | Default state |
squash | Merges into previous | Combining related logic |
fixup | Merges and discards log | Cleaning up typos/small fixes |
edit | Pauses for changes | Splitting or modifying content |
Avoiding Pitfalls
I once tried to rebase a branch that I had already pushed to a shared team repository. Don't do this. Rebase changes commit hashes, which effectively rewrites history. If your teammates have already pulled your changes, you’ll cause a massive headache for everyone involved.
If you accidentally mess up your history, don't panic. You can always use git reflog to find your previous state and reset your branch. It’s saved me more times than I care to admit, especially when I was still learning the ropes of git reset vs revert.
Should You Squash Everything?
I’ve seen engineers try to squash their entire PR into one massive commit. While that’s sometimes requested by maintainers—and you can learn more about that in our guide on git squash and merge—I prefer to keep logical chunks of work separate.
If I’m adding a new API endpoint and updating the documentation, I’ll often keep those as two distinct commits even after cleaning up the history. It makes the code review process much more digestible.
If you ever need to pull in changes from another branch before performing your cleanup, remember that git cherry-pick is a great way to grab specific work without bringing over the entire history of a feature branch.
Final Thoughts
Mastering git history cleanup is a superpower that signals you care about your team’s time. I still occasionally have "oh no" moments during a complex rebase, but the ability to fix my local history before it hits the server is worth the occasional friction.
Next time you’re about to open a PR, take that extra three minutes to run an interactive rebase. Your future self—and your reviewers—will thank you.
FAQ
Can I rebase commits that I’ve already pushed to a remote branch? Only if you are the only person working on that branch. If others have pulled your commits, rebasing will break their local history.
What happens if I encounter a merge conflict during a rebase?
Git will pause the rebase. You’ll need to resolve the conflicts, run git add <file>, and then run git rebase --continue.
Is there a way to automate the squash process?
Yes, you can use git commit --fixup <hash> during your workflow, and then run git rebase -i --autosquash to automatically arrange the commits for you.
