Interactive Rebase: squash, edit, reorder
Reviewed & published by Brayan K
Interactive rebase is the editor for your recent history. By the end of this lesson you'll squash messy work-in-progress commits into clean ones, reword and reorder commits, drop mistakes, and pause to edit a commit's content — all before you share your work.
Part of the free Git course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.
What You'll Learn
- Open an interactive rebase with git rebase -i HEAD~n
- Read and edit the 'todo' list of commits
- pick, reword, edit, squash, fixup, and drop actions
- Squash several commits into one tidy commit
- Reorder commits by reordering lines
- Apply the golden rule on shared commits
1️⃣ Opening an Interactive Rebase
git rebase -i HEAD~3 opens an editor with a todo list of your last three commits, oldest at the top. Each line starts with an action word (default pick) followed by the commit. You change the action words, optionally reorder the lines, then save and close to apply.
# Interactive rebase lets you REWRITE a series of recent commits:
# squash them together, fix messages, reorder, or drop them entirely.
# Open an editable "todo" list of the last 3 commits
git rebase -i HEAD~3
# Git opens an editor pre-filled like this (oldest at the TOP):
# pick a1b2c3d Add login form
# pick b2c3d4e Fix typo in login form
# pick c3d4e5f Add login validation
#
# Change the word at the start of each line to choose an action,
# reorder the lines to reorder commits, then save & close.2️⃣ The Actions
A quick tour: pick keeps a commit as-is; reword keeps it but edits the message; squash folds it into the commit above and combines messages; fixup does the same but discards this commit's message; edit pauses so you can amend its content; drop deletes it. Reorder commits just by reordering the lines.
# The actions you'll reach for most:
#
# pick keep the commit exactly as it is (the default)
# reword keep the changes, but edit the commit MESSAGE
# squash fold this commit into the one ABOVE it, combine messages
# fixup fold into the one above, but THROW AWAY this message
# edit pause here so you can amend the commit's content
# drop delete this commit entirely
#
# Reorder commits simply by reordering the lines.
# Example todo: squash the typo fix into the form commit, reword the last
pick a1b2c3d Add login form
fixup b2c3d4e Fix typo in login form
reword c3d4e5f Add login validation3️⃣ Squashing Commits
The classic use is collapsing several messy commits into one before a pull request. Keep the first as pick and mark the rest squash (or fixup to drop their messages). On saving, Git opens a second editor so you can write one clean combined message.
# A super common cleanup: turn three messy WIP commits into one tidy commit
# before opening a pull request.
git rebase -i HEAD~3
# In the editor, keep the first as pick and squash the rest into it:
# pick a1b2c3d Start search feature
# squash b2c3d4e wip
# squash c3d4e5f more wip, fix bug
#
# Save & close. Git then opens a second editor to combine the three
# messages into one — clean it up to a single clear message and save.Your turn. Squash three commits into one and reword it. Fill in the two blanks.
# 🎯 YOUR TURN — replace each ___ then follow the steps in your terminal.
# Goal: squash three messy commits into one and reword it.
# 1) Open an interactive rebase over the last 3 commits
git rebase ___ HEAD~3 # 👉 the flag that makes a rebase interactive
# 2) In the editor, keep the first line as "pick" and change the next two
# lines' action to ___ so they fold into the first commit.
# 👉 the action that melds a commit into the one above it
# 3) Save & close, then in the message editor write one clear message.
# ✅ Expected: "git log --oneline" now shows ONE commit where there were
# three, with the single message you wrote.Common Errors (and the fix)
- Squashed in the wrong direction: squash/fixup fold into the line above. The first line can't be squashed — keep it pick.
- Rebase stopped after an edit line: that's intentional — amend the commit, then run git rebase --continue.
- Conflict mid-rebase: resolve, git add, then git rebase --continue — never git commit.
- Made a mess of the todo list: bail out cleanly with git rebase --abort and start over.
- Rewrote pushed commits: don't — interactive rebase rewrites history. Clean up before pushing.
Pro Tips
- 💡 Clean up before the PR: squash WIP noise so reviewers see clear, logical commits.
- 💡 fixup for noise, squash for keepers: use fixup when a commit's message is worthless.
- 💡 --abort is always there: nothing is final until the rebase completes.
- 💡 Autosquash: git commit --fixup=<hash> + rebase -i --autosquash automates fixups.
📋 Quick Reference
| Action / Command | Meaning |
|---|---|
| git rebase -i HEAD~n | Edit the last n commits |
| pick | Keep the commit unchanged |
| reword | Keep commit, edit its message |
| squash | Fold into previous, combine messages |
| fixup | Fold into previous, drop this message |
| edit | Pause to amend the commit |
| drop | Delete the commit |
Mini-Challenge: Polish Before a PR
No commands given this time — just the plan. Turn four messy commits into a clean, shareable set.
# 🎯 MINI-CHALLENGE: polish a branch before a pull request.
# No commands given — just the plan. Run each step in your terminal.
#
# 1. On a feature branch, make 4 commits including a couple of "wip" ones
# and one with a bad message
# 2. Run "git rebase -i HEAD~4"
# 3. fixup the "wip" commits into a real one (discarding their messages)
# 4. reword the bad-message commit into something clear
# 5. Optionally reorder so related commits sit together; save & close
#
# ✅ Expected: a clean, minimal set of commits with clear messages, ready
# to share. (Only do this on LOCAL, unpushed commits!)
# your commands here🎉 Lesson Complete!
- ✅ git rebase -i HEAD~n opens an editable todo list of commits
- ✅ pick, reword, edit, squash, fixup, drop are the actions
- ✅ squash keeps both messages; fixup discards the folded commit's message
- ✅ Reorder commits by reordering the lines
- ✅ It rewrites history — only use it on local, unpushed commits
Practice quiz
What does `git rebase -i` open?
- A merge tool
- The remote settings
- An editable 'todo' list of commits with actions
- A diff viewer
Answer: An editable 'todo' list of commits with actions. Interactive rebase opens an editor listing the commits and the action to take on each.
In `git rebase -i HEAD~3`, what does HEAD~3 select?
- The last 3 commits to replay/edit
- The 3rd commit only
- 3 branches
- The first 3 commits ever
Answer: The last 3 commits to replay/edit. HEAD~3 picks the three most recent commits for the interactive rebase.
What does the `pick` action do?
- Deletes the commit
- Merges it
- Renames the branch
- Keeps the commit as-is
Answer: Keeps the commit as-is. pick keeps the commit unchanged — it's the default action for each line.
What does `squash` (s) do?
- Deletes a commit
- Combines a commit into the previous one, keeping BOTH messages to edit
- Reverses a commit
- Splits a commit
Answer: Combines a commit into the previous one, keeping BOTH messages to edit. squash folds the commit into the one above and lets you combine the messages.
How does `fixup` (f) differ from `squash`?
- fixup combines into the previous commit but DISCARDS the fixup's message
- fixup keeps both messages
- fixup deletes the commit
- There is no difference
Answer: fixup combines into the previous commit but DISCARDS the fixup's message. fixup melds the change into the prior commit and throws away its message.
What does `reword` (r) do?
- Rewrites the code
- Deletes the message
- Keeps the commit but lets you change its message
- Reorders commits
Answer: Keeps the commit but lets you change its message. reword keeps the commit's changes but prompts you to edit its message.
What does `edit` (e) let you do?
- Only change the message
- Pause at that commit so you can amend its content or split it
- Delete the commit
- Skip the commit
Answer: Pause at that commit so you can amend its content or split it. edit stops the rebase at that commit so you can amend its contents.
How do you DROP a commit entirely in interactive rebase?
- Use 'pick'
- Use 'squash'
- Use 'reword'
- Use the 'drop' action or delete its line
Answer: Use the 'drop' action or delete its line. Mark the line drop (or remove the line) to discard that commit.
How do you REORDER commits in an interactive rebase?
- You can't reorder
- Rearrange the lines in the todo list
- Use git reorder
- Change their hashes
Answer: Rearrange the lines in the todo list. Reordering the lines in the todo editor reorders the commits when applied.
Is interactive rebase safe to use on already-pushed, shared commits?
- Yes, always
- Only with fixup
- No — like all rebasing, it rewrites history and shouldn't touch shared commits
- Only on main
Answer: No — like all rebasing, it rewrites history and shouldn't touch shared commits. Interactive rebase rewrites history, so the golden rule still applies: don't rewrite shared commits.
Continue this course
- Previous: Rebasing Branches
- Next: Cherry-Picking Commits — Apply a specific commit from one branch onto another with git cherry-pick
- Quick reference: Git cheat sheet › Rebase & Cherry-pick
Frequently asked questions
What is interactive rebase for?
git rebase -i lets you rewrite a series of recent commits before sharing them. You can squash several commits into one, reword messages, reorder commits, pause to edit a commit's contents, or drop commits entirely. It's the standard way to turn a messy string of work-in-progress commits into a clean, readable history before opening a pull request.
What's the difference between squash and fixup?
Both fold a commit into the one directly above it in the todo list. The difference is the message: squash keeps both commits' messages and opens an editor so you can combine them, while fixup melds the change in but silently discards the squashed commit's message, keeping only the message of the commit above. Use fixup for throwaway 'wip' commits whose messages you don't want.
How do I reorder commits?
In the interactive rebase editor, each commit is one line, with the oldest at the top. To reorder commits, simply rearrange those lines and save. Git applies them in the new order. Be aware that reordering commits that touch the same code can cause conflicts, which you resolve and then continue with git rebase --continue.
What does the 'edit' action do?
Marking a commit with edit makes the rebase pause right after applying that commit, dropping you back at the shell. There you can amend its contents (git commit --amend), or even split it into multiple commits, before running git rebase --continue to resume. It's the tool for fixing the contents of an older commit, not just its message.
Is interactive rebase safe?
It's safe on local, unpushed commits and is reversible mid-flight with git rebase --abort. But it rewrites history, so the golden rule of rebasing still applies: never run it on commits you've already pushed and shared, because the rewritten commits get new hashes that diverge from what your teammates already have. Clean up before you push, not after.