What is Git Rebase Interactive Mode?
Git rebase interactive mode is a powerful tool that lets you rewrite your commit history by
modifying, reordering, squashing, or removing commits before they are integrated into a branch.
It is invoked with git rebase -i and opens an editor where you can craft exactly
how your commit timeline should look. Instead of blindly replaying commits, interactive mode
gives you full control over each commit in the range you select.
In a typical Git workflow, you make commits as you progress through a feature. Often these intermediate commits are messy — they might include “WIP” snapshots, fixup commits for typos, or logically grouped changes split across several commits. Interactive rebase allows you to polish this local history into a clean, logical sequence of well-described commits before sharing your work with others.
Why Does Interactive Rebase Matter?
🚀 Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →A clean commit history is an asset for any project. It makes code reviews easier, speeds up bisecting to find bugs, and improves the readability of the project’s evolution. Interactive rebase is the primary tool to achieve this. It matters because:
- Clarity in history: Squashing related fixes into the original commit means the final history tells a coherent story, not a step-by-step log of every typo fix.
- Better code review: Reviewers see well-structured commits with clear messages, making it easier to understand intent and changes.
-
Simplified debugging:
git bisectbecomes more effective when each commit is a logically complete unit that compiles and works correctly. - Professional collaboration: In open source and team environments, maintainers often require a clean commit history before merging pull requests.
Getting Started with Interactive Rebase
The basic syntax is:
git rebase -i <base-commit>
<base-commit> can be a branch name, a commit hash, or a relative reference
like HEAD~3 to specify the last three commits. For example:
git rebase -i HEAD~4
This will open an editor showing the last four commits in reverse chronological order (oldest
first) with a list of available commands. Each line starts with the word pick and
the commit hash and message. You change the command word to alter what happens to that commit.
Understanding the Rebase Commands
The editor presents a “todo” list. Each line has the format:
<command> <commit-hash> <commit-message>
The available commands are:
-
pick(orp) – use the commit as-is. This is the default. -
reword(orr) – use the commit but stop to edit the commit message. -
edit(ore) – use the commit but stop for amending. You can split the commit or add more changes. -
squash(ors) – combine the commit with the previous one. Git will open an editor to merge the commit messages. -
fixup(orf) – like squash, but discard the commit’s log message and only keep the previous commit’s message. -
drop(ord) – remove the commit entirely, as if it never happened. -
exec– run a shell command after the commit is replayed (useful for running tests).
You can also reorder the lines simply by moving them up or down. The order in the editor determines the new chronological order of commits.
Step-by-Step Example
Let’s walk through a real scenario. Suppose you have a feature branch with the following history:
git log --oneline
a1b2c3d Add final feature X (typo fix)
e4f5g6h WIP intermediate stuff
i7j8k9l Initial implementation of feature X
You want to end up with two clean commits: one for the initial implementation and one for the final feature, squashing the WIP and typo fix into meaningful units. Start the interactive rebase:
git rebase -i HEAD~3
The editor shows:
pick i7j8k9l Initial implementation of feature X
pick e4f5g6h WIP intermediate stuff
pick a1b2c3d Add final feature X (typo fix)
Change it to:
pick i7j8k9l Initial implementation of feature X
squash e4f5g6h WIP intermediate stuff
reword a1b2c3d Add final feature X (typo fix)
Save and close. Git will first combine the second commit into the first, opening an editor to let you craft a message for the squashed commit. You might write:
Implement core logic for feature X
Then Git stops for the reword on the last commit, letting you change its message
to something like:
Add final tests and documentation for feature X
After saving, the rebase completes. The new history looks like:
git log --oneline
<new-hash> Add final tests and documentation for feature X
<new-hash> Implement core logic for feature X
The commits are now atomic, well-described, and ready for a pull request.
Rewording Commit Messages
If you only need to fix a typo or improve a commit message, use reword:
git rebase -i HEAD~2
Mark the commit you want to change with reword instead of pick. Git
will pause and ask you to enter a new message.
# Original
pick abc123 Fix login btton color
# Change to
reword abc123 Fix login btton color
After saving, Git opens the commit message editor. Correct the typo:
Fix login button color
The commit hash will change, but the content stays identical.
Squashing Commits
Squashing combines multiple commits into one. This is ideal when you have several small fixup
commits after a main commit. In the todo list, change later commits to squash or
fixup:
pick def456 Add user profile page
squash ghi789 Fix missing avatar placeholder
squash jkl012 Update avatar upload logic
This will combine all three into a single commit. Git prompts you to edit the combined commit message, which by default concatenates the original messages. You can delete or rewrite them into a single coherent message like:
Add user profile page with avatar upload
Using fixup instead of squash skips the message editor and
automatically uses the first commit’s message, discarding the others. This is perfect for
trivial “oops” commits:
pick def456 Add user profile page
fixup ghi789 Fix typo in profile page header
fixup jkl012 Remove debug log
After rebase, only “Add user profile page” remains, with all changes included.
Splitting Commits with Edit
Sometimes a commit mixes unrelated changes. The edit command lets you stop and
break it apart. For example, a commit adds both a new API endpoint and updates the CSS styles.
git rebase -i HEAD~2
Mark the commit with edit:
edit mno345 Add API endpoint and restyle dashboard
pick pqr678 Update documentation
Git will stop after applying that commit. Now you can reset the commit to keep the changes staged but not committed:
git reset HEAD^
Your working directory now has all the changes from that commit as unstaged modifications. Stage and commit the API changes first:
git add api/endpoint.js
git commit -m "Add new API endpoint"
Then commit the style changes:
git add styles/dashboard.css
git commit -m "Restyle dashboard for new layout"
Once you have the desired commits, continue the rebase:
git rebase --continue
The rest of the rebase proceeds normally. The original mixed commit is replaced by two focused commits.
Reordering Commits
You can simply move lines in the todo list to change the order of commits. For instance, if a documentation commit accidentally appears before the code it describes, swap them:
# Before editing
pick abc123 Add new feature
pick def456 Update feature documentation
Change to:
pick def456 Update feature documentation
pick abc123 Add new feature
After saving, the documentation commit will come first. Be careful: reordering can cause conflicts if later commits depend on earlier ones. Resolve conflicts as you would with a normal rebase.
Best Practices
Interactive rebase is powerful but requires discipline. Follow these guidelines to avoid problems:
- Never rebase shared branches. Only rebase commits that exist only in your local repository or in a private feature branch. Rewriting public history causes chaos for collaborators.
-
Keep commits atomic. Each commit should represent a single logical change
that compiles and passes tests. This makes
git bisectuseful and reviews easier. - Use fixup/squash for WIP commits. Commit frequently while developing, then squash those micro-commits into meaningful units before pushing.
- Rebase early and often. Perform interactive cleanup while the feature is fresh in your mind. Don’t let messy history accumulate.
-
Verify after rebase. Always run tests and do a quick sanity check with
git logandgit diff main..HEADto confirm nothing is broken. -
Back up before complex rebases. Use
git branch backup-branchbefore a risky rebase, so you can recover if something goes wrong. -
Use
--autosquashfor fixup chains. If you create fixup commits withgit commit --fixup <target-commit>, you can later rungit rebase -i --autosquash HEAD~nto automatically order and mark them as fixup, saving manual editing.
Conclusion
Git rebase interactive mode transforms messy, incremental development histories into clean,
logical narratives. By mastering pick, reword, squash,
fixup, edit, and drop, you gain the ability to craft a
commit history that is easy to review, understand, and maintain. While it requires care — always
avoid rewriting public commits — the practice of regularly cleaning your local history leads to
better collaboration and a more professional codebase. Start incorporating interactive rebase
into your daily workflow, and you’ll quickly wonder how you ever managed without it.