🎬 Git Time Travel: Rewriting Your Story
Imagine you’re writing a book. You’ve written several chapters, but you realize:
- Chapter 3 should come after Chapter 5
- Some chapters have spelling mistakes
- You want to combine two short chapters into one
In regular writing, you’d erase and rewrite. In Git, you can do the same thing with your code history!
This is called Modifying History — and it’s like having a magical eraser that lets you clean up your story before showing it to the world.
🌳 What is Rebasing?
The Simple Analogy
Think of your Git history like a family tree:
Grandpa (main branch)
↓
Dad
↓
You (feature branch)
Rebasing is like saying: “I want to pretend I was born from a different parent.”
The Problem Rebasing Solves
You started working on a feature. Meanwhile, your teammate added new code to main.
Before rebase:
main: A → B → C (teammate's new work)
↓
feature: D → E (your work)
Your work is based on old code (B). You want it based on new code ©.
After rebase:
main: A → B → C
↓
feature: D' → E' (your work, now based on C!)
How to Rebase
# On your feature branch
git checkout feature
# Rebase onto main
git rebase main
What happens:
- Git “picks up” your commits (D, E)
- Moves to latest main ©
- “Replays” your commits on top
🎯 Key Point: Your commits get new IDs (D becomes D’, E becomes E’). They’re the same changes, but with new “birth certificates.”
🎮 Interactive Rebasing: The Ultimate Control
What is Interactive Rebasing?
Regular rebasing just moves commits. Interactive rebasing lets you:
- ✏️ Edit commit messages
- 🗑️ Delete commits
- 📦 Combine commits together
- 🔀 Reorder commits
It’s like having a video editor for your Git history!
How to Use It
# Edit the last 3 commits
git rebase -i HEAD~3
This opens a text editor showing:
pick abc1234 Add login button
pick def5678 Fix typo in login
pick ghi9012 Style login button
The Magic Words
| Command | What It Does | Example |
|---|---|---|
pick |
Keep this commit | Use it as-is |
reword |
Change message | Fix a typo in commit text |
edit |
Stop and edit | Change the actual code |
squash |
Combine with previous | Merge two commits |
fixup |
Combine, drop message | Merge silently |
drop |
Delete commit | Remove entirely |
Example: Combining Commits
Your history looks messy:
pick abc1234 Add login
pick def5678 oops forgot semicolon
pick ghi9012 fixed another typo
Change to:
pick abc1234 Add login
fixup def5678 oops forgot semicolon
fixup ghi9012 fixed another typo
Result: One clean commit: “Add login” ✨
⚔️ Rebase vs Merge: The Great Debate
The Birthday Party Analogy
Merge is like taking a group photo:
“Here’s everyone who came to the party, exactly as it happened.”
Rebase is like arranging people in a neat line:
“Let me organize this to look cleaner.”
Visual Comparison
Merge creates a “merge commit”:
A → B → C
↘ ↘
D → E → F → M (merge commit)
Rebase creates a straight line:
A → B → C → D' → E' → F'
When to Use Each
| Situation | Use This | Why |
|---|---|---|
| Public/shared branch | Merge | Others have your commits |
| Private/local branch | Rebase | Clean history, no one affected |
| Want to preserve history | Merge | Shows exactly what happened |
| Want clean history | Rebase | Linear, easy to read |
The Golden Rule
⚠️ Never rebase commits that others have already pulled!
Rebasing changes commit IDs. If someone has your old commits, they’ll have conflicts with your new ones.
🎯 Rebase Onto: Surgical Precision
The Problem
You started a feature from the wrong branch:
main: A → B
↓
develop: C → D
↓
feature: E → F (oops, wanted this from main!)
The Solution
git rebase --onto lets you move commits to a different base:
git rebase --onto main develop feature
Translation: “Take feature’s commits that came after develop, and put them on main instead.”
Result:
main: A → B
↓
E' → F' (now based on main!)
develop: A → B → C → D
Breaking Down the Command
git rebase --onto <new-base> <old-base> <branch>
| Part | Meaning |
|---|---|
<new-base> |
Where you want commits to go |
<old-base> |
Where commits currently start from |
<branch> |
The branch with commits to move |
🍒 Cherry-Picking: One Commit at a Time
What is Cherry-Picking?
Imagine a bowl of cherries (commits). You don’t want all of them — just a few specific ones.
Cherry-picking = grabbing one specific commit and putting it somewhere else.
When to Use It
- Bug fix exists on one branch, needed on another
- Accidentally committed to wrong branch
- Want specific changes without merging everything
How to Cherry-Pick
# Find the commit you want
git log --oneline
# Output: abc1234 Fix critical bug
# Switch to target branch
git checkout main
# Pick that specific commit
git cherry-pick abc1234
Result: The fix is now on main too!
Cherry-Picking Multiple Commits
# Pick several commits
git cherry-pick abc1234 def5678
# Pick a range of commits
git cherry-pick abc1234..ghi9012
Handling Conflicts
If there’s a conflict:
# Fix the conflict in your editor
git add .
# Continue the cherry-pick
git cherry-pick --continue
# Or abort if you change your mind
git cherry-pick --abort
🛡️ Rewriting History Safely
The Danger Zone
Rewriting history can cause serious problems if done wrong:
- Teammates can’t pull your changes
- Commits can be lost forever
- Confusion and frustration
Safety Rules
-
Only rewrite unpushed commits
# Check what's not pushed yet git log origin/main..HEAD -
Create a backup branch first
git branch backup-before-rebase -
Use
--force-with-leaseinstead of--force# Safe force push (fails if someone else pushed) git push --force-with-lease # NOT this (dangerous, overwrites everything) # git push --force
The Reflog: Your Safety Net
Did something go wrong? Git remembers everything:
# See all recent actions
git reflog
# Output:
# abc1234 HEAD@{0}: rebase finished
# def5678 HEAD@{1}: rebase: Add login
# ghi9012 HEAD@{2}: rebase started
# xyz7890 HEAD@{3}: commit: Original commit (before rebase!)
# Go back to before the rebase
git reset --hard xyz7890
💡 Tip: The reflog keeps entries for 90 days. You can almost always undo mistakes!
Safe History Rewriting Checklist
graph TD A["Want to rewrite history?"] --> B{Are commits pushed?} B -->|No| C["✅ Safe to rewrite"] B -->|Yes| D{Do others have them?} D -->|No| E["⚠️ Use force-with-lease"] D -->|Yes| F[❌ Don't rewrite! Use revert instead]
🎯 Quick Reference
| Task | Command |
|---|---|
| Simple rebase | git rebase main |
| Interactive rebase | git rebase -i HEAD~3 |
| Rebase onto | git rebase --onto new old branch |
| Cherry-pick | git cherry-pick <commit> |
| Safe force push | git push --force-with-lease |
| Undo with reflog | git reflog then git reset --hard <ref> |
| Abort any rebase | git rebase --abort |
🎬 Putting It All Together
Think of these tools as your history editing studio:
- Rebase = Move your work to a new foundation
- Interactive Rebase = Edit, combine, reorder commits
- Rebase Onto = Surgically transplant commits
- Cherry-Pick = Copy specific commits anywhere
- Reflog = Your undo button for everything
The Journey
graph TD A["Messy History"] --> B["Rebase: Clean foundation"] B --> C["Interactive Rebase: Polish commits"] C --> D["Cherry-Pick: Move specific fixes"] D --> E["Clean, Professional History!"]
Remember: Your local history is your draft. Clean it up before sharing!
🚀 You’ve got this! These tools might seem scary at first, but they’re just ways to tell a cleaner story. Start with simple rebases, then try interactive mode. Soon you’ll be editing history like a pro!
