Rewriting the Past: A Guide to Git Interactive Rebase
Overview
Maintaining a clean commit history isn't just about vanity; it's about communication. When you open a pull request, your history tells a story to the reviewer.
Prerequisites
To get the most out of this tutorial, you should be comfortable with basic Git operations like git add, git commit, and git log. Familiarity with terminal-based text editors—specifically
Key Libraries & Tools
- Git: The core distributed version control system used for all commands.
- Vim: A terminal-based text editor often used as the default interface for rebase todo lists.
- Z: A command-line tool mentioned by Rissa Jacksonfor quickly navigating between project directories.
Code Walkthrough: Cleaning Your History
The Interactive Command
To start a rebase, you need to point Git to the commit before the ones you want to edit. Using the tilde (~) notation is the most reliable method.
git rebase -i [commit-hash]~
This opens an interactive list. Each line starts with the word pick. To change the history, you replace pick with a specific command.
Dropping and Rewording
If you have a commit that should never have existed, like a test file you accidentally committed, use the drop command. For simple typos in a commit message, use reword.
# Interactive Rebase Todo List
reword a1b2c3d Fix typo in post model
drop e5f6g7h Delete me: temporary debugging
pick i9j0k1l Add actual feature logic
Squashing and Fixing Up
These are the workhorses of a clean history. Both squash and fixup meld a "child" commit into the "parent" commit above it. The difference lies in the message: squash prompts you to combine both messages, while fixup discards the child’s message entirely.
# Using fixup to hide a small cleanup
pick a1b2c3d Main feature work
fixup e5f6g7h Oops, forgot a semicolon
Syntax Notes
You don't need to use the full 40-character SHA-1 hash. Git usually understands the first seven characters. In the rebase editor, simply changing the command word at the start of the line (e.g., from pick to f for fixup) is sufficient to trigger the change upon saving and exiting.
Tips & Gotchas
Rebasing is a destructive action because it generates new commit hashes. Never rebase commits that have already been pushed to a shared branch where others are working; you will break their history. If you must push rebased code to your own feature branch, use git push --force-with-lease. This "Canadian Force" command ensures you don't accidentally overwrite someone else's work if they added commits to the branch while you were rebasing locally. If things get confusing, your emergency exit is git rebase --abort.
