Interactive Rebase — Squash, Edit, Reword & Reorder Commits
In this tutorial, you'll learn about Interactive Rebase. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
What You'll Learn
Use git rebase --interactive to squash, reword, reorder, and split commits in Git — clean up your branch history before merging into main.
Why It Matters
A messy commit history with "fix typo" and "wip" commits is hard to review and impossible to revert cleanly. Interactive rebase lets you rewrite history so every commit tells a clear, logical story.
Real-World Use
Before merging a feature branch, you squash 12 incremental commits into 3 meaningful ones, reword two vague messages, and drop a debug commit — making the review take 10 minutes instead of an hour.
What Is Interactive Rebase?
Interactive rebase opens an editor where you choose an action for each commit in a range:
pick a1b2c3 Add login form
pick d4e5f6 fix typo
pick f7a8b9 add validation
pick c0d1e2 WIP
pick f3a4b5 finished validation
# Rebase 5 commits onto main
#
# Commands:
# p, pick = use commit
# r, reword = change message only
# s, squash = combine with previous commit
# d, drop = remove commit
# e, edit = stop to amend
The result after squashing and rewording:
pick a1b2c3 Add login form
squash d4e5f6 fix typo
squash f7a8b9 add validation
squash c0d1e2 WIP
pick f3a4b5 Add form validation
This produces 2 clean commits instead of 5 messy ones.
Basic Interactive Rebase
git checkout feature/login
git log --oneline main..HEAD
# a1b2c3 Add login form
# d4e5f6 fix typo
# f7a8b9 add validation
# c0d1e2 WIP
# f3a4b5 finished validation
# Rebase the last 5 commits
git rebase -i HEAD~5
# Editor opens with:
# pick a1b2c3 Add login form
# pick d4e5f6 fix typo
# pick f7a8b9 add validation
# pick c0d1e2 WIP
# pick f3a4b5 finished validation
Change the actions, save, and exit. Git applies them one-by-one.
Squashing Commits
Combine multiple commits into one:
# Before rebase -i, change to:
pick a1b2c3 Add login form
squash d4e5f6 fix typo
squash f7a8b9 add validation
squash c0d1e2 WIP
# Save and close. Git asks for a new combined message:
# Add login form
# fix typo
# add validation
# WIP
# Write a single clear message:
# Add login form with client-side validation
# Result: one commit with the combined changes
git log --oneline -3
# x7y8z9 Add login form with client-side validation
# f3a4b5 finished validation
Rewording Commits
Change a commit message without changing its content:
# In rebase -i, change to:
reword f3a4b5 finished validation
# Save. Git opens another editor for that commit.
# Change "finished validation" to:
# Add server-side validation checks
# Save again. The message is updated.
Reordering Commits
Move commits in the editor to reorder them:
# Before:
pick a1b2c3 Add login form
pick d4e5f6 Add config file # belongs first
pick f7a8b9 Add validation
# After (move config up):
pick d4e5f6 Add config file
pick a1b2c3 Add login form
pick f7a8b9 Add validation
Git replays them in the new order. If there are no conflicts, the history is cleanly rewritten.
Dropping Commits
Remove a commit entirely:
# Before:
pick a1b2c3 Add login form
pick d4e5f6 debug output
pick f7a8b9 Add validation
# Change to:
pick a1b2c3 Add login form
drop d4e5f6 debug output
pick f7a8b9 Add validation
# The debug commit is gone. Its changes are not applied.
Editing a Commit
Stop at a commit to make changes:
# In rebase -i:
edit a1b2c3 Add login form
# Git stops after applying this commit.
# Make changes:
echo "new field" >> login.py
git add login.py
git commit --amend # Update the commit
git rebase --continue
Aborting a Rebase
If something goes wrong:
git rebase --abort
# Returns to the original state before rebase started
Mermaid: Interactive Rebase Flow
graph LR
A[Start: git rebase -i HEAD~N] --> B[Editor opens with commit list]
B --> C{Choose action per commit}
C -->|pick| D[Keep as is]
C -->|reword| E[Edit message]
C -->|squash| F[Merge into previous]
C -->|drop| G[Remove commit]
C -->|edit| H[Stop to amend]
D --> I[Continue rebase]
E --> I
F --> I
G --> I
H --> I
I --> J{Conflicts?}
J -->|Yes| K[Resolve & git add / git rebase --continue]
J -->|No| L[Next commit]
K --> L
L --> M{More commits?}
M -->|Yes| C
M -->|No| N[Done: history rewritten]
Common Pitfalls
| Mistake | Solution |
|---|---|
| Rebasing commits already pushed | Never rebase public history — use git revert instead |
| Forgetting to squash before merge | Set up branch protection rules |
| Conflict during rebase | git rebase --abort and retry with smaller range |
| Losing dropped commits by accident | git reflog to recover before rebase expires |
Practice Questions
- What is the difference between
squashandfixupin interactive rebase? - How do you abort an interactive rebase that went wrong?
- Why should you never rebase commits that have already been pushed to a shared branch?
FAQs
Next Steps
Now that you can clean up branch history with interactive rebase, learn Git Worktrees to work on multiple branches simultaneously, or explore Git Hooks to automate quality checks before every commit.
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro