[!NOTE] “History is written by the victors.” — Winston Churchill
In Git, history is written by you, using Interactive Rebase.

Rebase is powerful, but Interactive Rebase (git rebase -i) is the scalpel of Git. It allows you to surgically alter your commit history before sharing it with others. You can squash typo fixes, reorder features, and polish your work into a coherent narrative.

The Hardware Reality: What Happens on Disk?

Before we start rewriting history, you must understand what “rewriting” actually means.

In Git, a Commit is immutable. Its SHA-1 hash is calculated from its content, parent, and message. If you change anything—even a single letter in the commit message—the hash changes.

When you “rebase”, Git is not changing old commits. It is:

  1. Creating NEW commit objects with the changes you requested.
  2. Moving the Branch Pointer (HEAD) to these new commits.
  3. Abandoning the old commits (which will eventually be garbage collected).
A B C Old HEAD Rebase (Squash B+C) A D New HEAD

The Interactive Rebase Simulator

Before we dive into the terminal, let’s visualize how interactive rebase works. Below is a list of commits. Imagine this is the “todo list” Git opens in your text editor.

Try to:

  1. Squash the “WIP” commits into the main feature.
  2. Drop the accidental file upload.
  3. Reorder the documentation commit to be first.

Todo List (HEAD~5)

Oldest commits are at the top, newest at the bottom.

New History (New SHA-1s Generated):

Anatomy of git rebase -i

To start an interactive rebase, you typically reference how far back you want to go.

# Rebase the last 5 commits
git rebase -i HEAD~5

This opens your configured text editor (Vim, Nano, VS Code, etc.) with a list of commits.

The Commands

Git provides several commands to manipulate commits. The default is pick, which keeps the commit as is.

Command Short Description
pick p Use commit as is.
reword r Use commit, but edit the commit message.
edit e Use commit, but stop for amending (allows splitting commits).
squash s Use commit, but meld into previous commit.
fixup f Like “squash”, but discard this commit’s log message.
exec x Run command (the rest of the line) using shell.
drop d Remove commit.

[!TIP] You can reorder commits simply by moving the lines up or down in your editor. Git will apply them in the new order.

Common Scenarios

1. Cleaning up “WIP” Commits

We’ve all done it. You commit “work in progress”, then “fix typo”, then “fix tests”. Before merging, you should combine these into one clean atomic commit.

Before:

pick 1a2b3c Feature X: initial structure
pick 4d5e6f WIP: logic implementation
pick 7g8h9i fix: syntax error
pick 0j1k2l Feature X: complete implementation

Instruction: Change pick to fixup (or f) for the intermediate commits.

After (in editor):

pick 1a2b3c Feature X: initial structure
fixup 4d5e6f WIP: logic implementation
fixup 7g8h9i fix: syntax error
fixup 0j1k2l Feature X: complete implementation

This results in one single commit containing all the changes, using the message from the first commit.

2. Rewording a Bad Commit Message

If you made a typo in a previous commit message, reword allows you to fix it without changing the code.

reword 3a4b5c Add featuree Z  <-- Git will pause and ask for new message
pick 6d7e8f Fix bug in Y

3. Splitting a Commit

Sometimes a commit does too much. Use edit to break it apart.

  1. Mark the commit with edit in the rebase list.
  2. Git will pause at that commit.
  3. Reset the commit (keeping changes in working dir): git reset HEAD~1
  4. Add files selectively: git add component A
  5. Commit: git commit -m "Feat: Component A"
  6. Add remaining files: git add component B
  7. Commit: git commit -m "Feat: Component B"
  8. Continue rebase: git rebase --continue

The Golden Rule of Rebase

[!WARNING] Never rebase public history.

If you have pushed it, do not rebase it. Use git revert instead.

Handling Conflicts

Rebasing actually reapplies commits one by one. If a conflict occurs:

  1. Git pauses and tells you which file has a conflict.
  2. Fix the conflict in your editor.
  3. Add the resolved file: git add <file>
  4. Do not commit!
  5. Continue: git rebase --continue

If things get too messy, you can always abort:

git rebase --abort

Summary

  • Squash/Fixup: Combine multiple commits into one.
  • Reword: Change commit messages.
  • Reorder: Change the order of commits.
  • Drop: Delete commits entirely.
  • Edit: Pause to modify the content of a commit.
  • Rule: Only rebase local, unshared branches.