Git 4a 🧩 Rebasing
Rebasing rewrites commit history by replaying your branch’s commits on top of another branch. Where merge creates a merge commit and preserves both branches, rebase produces a linear history — as if you’d always been working from the latest main.
Key point: Rebase rewrites history. That’s its power and its danger. It gives you a clean, linear commit log. But it also means the commits are new — new hashes, new identities. Never rebase a branch others are working on.
What rebasing is
git rebase [branch-name] takes all commits from your current branch that aren’t in the target branch and reapplies them on top of the target’s latest commits.
It’s not a merge. It’s a replay. Each of your commits is applied to the new base, one at a time.
Visual example:
Before:
main: A---B---C---D
\
feature: E---F---G
After git checkout feature && git rebase main:
main: A---B---C---D
\
feature: E'---F'---G'
E', F', and G' are the same changes as E, F, and G, but they’re new commits applied on top of D. The original commits are gone from the branch’s history.
Why the commits are different: A commit hash is derived from its content, parent, author, and timestamp. Changing the parent (by rebasing onto a new base) changes the hash. The code changes are the same, but they’re new commits.
Rebase vs merge
Both integrate work from one branch into another. They produce different histories.
| Aspect | Rebase | Merge |
|---|---|---|
| History | Linear | Preserves branches |
| Commit hashes | New | Same |
| Merge commit | None | Yes |
| Readability | Cleaner | More accurate |
| Safety | Rewrites history | Non-destructive |
When to use rebase:
- For feature branches before merging into main
- When you want a cleaner, linear commit history
- To keep your branch up-to-date with main
When to use merge:
- When you want to preserve the actual history of when merges occurred
- When working on shared branches others are using
- For historical records showing where features were integrated
Why the trade-off matters: Rebase gives clean history at the cost of accuracy. Merge preserves accuracy at the cost of clutter. Neither is universally right — pick based on whether history fidelity or readability matters more for the branch.
Rebase example
A full walkthrough.
1. Create and switch to main
git checkout main
git pull origin main
Start from the latest main.
2. Create a feature branch
git checkout -b feature/new-login
3. Make commits on the feature branch
# Edit file1.js and commit
git add file1.js
git commit -m "Add login form validation"
# Edit file2.js and commit
git add file2.js
git commit -m "Implement password strength check"
Two commits on the feature branch.
4. Main gets updated meanwhile
git checkout main
git pull origin main # New commits added to main
git checkout feature/new-login
Someone else pushed to main. Your branch is now based on an older version.
5. Rebase the feature branch onto latest main
git rebase main
Git takes your two commits, rewinds them, and reapplies them on top of the latest main.
6. History now
main: A---B---C---D---E---F
\
feature: G'---H'
Your feature branch now starts from the latest main. Commits are new (G', H'), but the changes are preserved.
7. Merge into main
git checkout main
git merge feature/new-login
Because the feature is based on the latest main, the merge is a fast-forward — clean, linear history.
Why this workflow: Rebasing before merging gives you a linear history without merge commits. If you rebase first and then merge, main stays clean.
Interactive rebase
git rebase -i opens an editor showing your commits with commands.
git rebase -i [commit-hash]
Or with a relative reference:
git rebase -i HEAD~3
This targets the last three commits.
Commands in the editor:
| Command | Effect |
|---|---|
pick | Keep the commit as-is |
reword | Change the message |
edit | Stop and modify the commit |
squash | Combine with previous commit |
fixup | Combine, discard this commit’s message |
drop | Remove the commit |
exec | Run a shell command |
Example — squash two commits into one:
pick abc1234 Add login form
squash def5678 Fix typo in login form
Git combines both into a single commit and lets you edit the message.
Reorder commits:
pick def5678 Fix typo in login form
pick abc1234 Add login form
Swapping the lines reorders the commits.
Why interactive rebase is powerful: It’s how you clean up a messy feature branch before merging. Squash, reword, reorder — shape the history as if you’d written it perfectly the first time.
Never rebase shared branches
If you’ve already pushed a branch to a shared remote, rebasing causes problems for others:
- It rewrites commit history — the commits others have are replaced by new ones
- Others’ local copies go out of sync
- It can cause conflicts or loss of work
The commits your teammates based work on no longer exist on the remote. Their local references point to ghosts.
The rule: Rebase only branches that are private to you. Once a branch is shared, use merge.
Why it’s dangerous: Git tracks commits by hash. If you rewrite the hashes, everyone else’s history diverges. They’d have to force-reset their branches, potentially losing work.
Rebase with remote branches
If you must rebase a shared branch, use --force-with-lease instead of --force:
git push --force-with-lease
Why --force-with-lease is safer: It only pushes if the remote is exactly where you last saw it. If someone else pushed in the meantime, the push fails — instead of overwriting their work.
Only do this when you’re certain no one else is working on the branch.
Never use plain --force on a shared branch unless you’re absolutely sure. It overwrites the remote unconditionally.
Why the lease:
--forcesays “make the remote match my local state, no matter what.”--force-with-leasesays “make the remote match my local state, but only if nobody else has pushed since I last fetched.” The second is safer.
Rebase vs merge at a glance
┌──────────────────────────────────────────────┐
│ Merge │
│ │
│ main: A ──► B ──► C ──► M │
│ \ / │
│ D ──► E │
│ │
│ Preserves branch structure │
│ Creates a merge commit (M) │
│ Safe on shared branches │
│ │
└──────────────────────────────────────────────┘
┌──────────────────────────────────────────────┐
│ Rebase │
│ │
│ main: A ──► B ──► C │
│ \ │
│ D' ──► E' │
│ │
│ Linear history │
│ No merge commit │
│ Rewrites commits — unsafe on shared │
│ │
└──────────────────────────────────────────────┘
Complete Example Session
# ============================================
# PART 1: SETUP
# ============================================
git checkout main
git pull origin main
# ============================================
# PART 2: FEATURE BRANCH
# ============================================
git checkout -b feature/new-login
# Edit file1.js
git add file1.js
git commit -m "Add login form validation"
# Edit file2.js
git add file2.js
git commit -m "Implement password strength check"
# ============================================
# PART 3: MAIN MOVES FORWARD
# ============================================
git checkout main
git pull origin main
# [ Updating 1a2b3c4..5d6e7f8 ]
# [ Fast-forward ]
git checkout feature/new-login
# [ Switched to branch 'feature/new-login' ]
# ============================================
# PART 4: REBASE
# ============================================
git rebase main
# [ Successfully rebased and updated refs/heads/feature/new-login. ]
git log --oneline
# [ h8i9j0k (HEAD -> feature/new-login) Implement password strength check ]
# [ g7h8i9j Add login form validation ]
# [ f6g7h8i (main) Latest main commit ]
# [ ... ]
# ============================================
# PART 5: MERGE (FAST-FORWARD)
# ============================================
git checkout main
git merge feature/new-login
# [ Updating f6g7h8i..h8i9j0k ]
# [ Fast-forward ]
# [ file1.js | ... ]
# [ file2.js | ... ]
# ============================================
# PART 6: INTERACTIVE REBASE
# ============================================
git checkout -b feature/cleanup
# ... make 3 messy commits ...
git rebase -i HEAD~3
# [ Editor opens ]
# [ pick abc1234 Add login form ]
# [ squash def5678 Fix typo ]
# [ squash ghi9012 Fix typo again ]
# [ Save and close ]
# Git combines all three into one commit
# You edit the final message
# ============================================
# PART 7: FORCE-WITH-LEASE
# ============================================
git push --force-with-lease
# [ + abc1234...def5678 feature/cleanup -> feature/cleanup (forced update) ]
Quick Reference
Basic Rebase
| Command | Purpose |
|---|---|
git rebase main | Rebase current branch onto main |
git rebase -i COMMIT | Interactive rebase |
git rebase --continue | Continue after resolving conflict |
git rebase --abort | Abort the rebase |
git rebase --skip | Skip the current commit |
Interactive Commands
| Command | Effect |
|---|---|
pick | Keep as-is |
reword | Edit message |
edit | Modify commit |
squash | Combine with previous |
fixup | Combine, discard message |
drop | Remove |
exec | Run shell command |
Rebase vs Merge
| Use rebase | Use merge |
|---|---|
| Private branch | Shared branch |
| Before merging | After diverging |
| Clean history | Accurate history |
| Single author | Multiple authors |
Safety
| Command | Safe? |
|---|---|
git rebase main | ✅ on private branches |
git push --force | ❌ dangerous |
git push --force-with-lease | ✅ safer |
git rebase on shared | ❌ avoid |
Rebase Conflicts
| Command | Purpose |
|---|---|
git status | See conflicts |
| Edit | Resolve markers |
git add FILE | Stage resolution |
git rebase --continue | Resume |
git rebase --abort | Cancel |
Best Practices
✅ Do This:
# Rebase your feature branch before merging
git checkout feature/login
git rebase main # ✅
# Use interactive rebase to clean up
git rebase -i HEAD~5 # ✅
# Resolve conflicts and continue
git add file.js
git rebase --continue # ✅
# Use --force-with-lease when pushing
git push --force-with-lease # ✅
# Abort if things go wrong
git rebase --abort # ✅
# Rebase only private branches
# Never rebase shared ones # ✅
❌ Don’t Do This:
# Don't rebase a shared branch
git rebase main # ❌ on shared
git push --force # ❌ overwrites others
# Don't force-push without a lease
git push --force # ❌
# Don't rebase after merging to main
# It's already public # ❌
# Don't skip testing after rebase
# The code changed # ⚠️
# Don't rebase to avoid merge conflicts
# Resolve them instead # ⚠️
# Don't rebase a branch that's been pulled
# Others depend on those hashes # ❌
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
| Rebasing shared branch | Others’ history breaks | Merge instead |
| Force-pushing without lease | Overwrites others | --force-with-lease |
| Conflicts during rebase | Rebase pauses | Resolve, --continue |
| Forgetting to push after rebase | Remote out of date | Push with lease |
| Rebasing a merged branch | Nothing to rebase | No-op or abort |
| Losing commits | Wrong range | Verify with git log |
| Rebasing without testing | Silent breakage | Test after |
Real-World Examples
1. Rebase onto main
git checkout feature/login
git rebase main
Updates the feature branch to the latest main.
2. Interactive rebase
git rebase -i HEAD~3
Opens the last 3 commits for editing.
3. Squash commits
pick abc1234 Add feature
squash def5678 Fix
squash ghi9012 Fix again
Three commits become one.
4. Reorder commits
pick def5678 Fix
pick abc1234 Add feature
Swapping lines reorders them.
5. Reword a commit
reword abc1234 Add feature
Opens the editor to change the message.
6. Continue after conflict
git add file.js
git rebase --continue
Resumes the rebase.
7. Abort rebase
git rebase --abort
Returns to the pre-rebase state.
8. Skip a commit
git rebase --skip
Drops the current commit from the rebase.
9. Force-with-lease
git push --force-with-lease
Pushes safely after a rebase.
10. Verify after rebase
git log --oneline
Confirm the new history looks right.
11. Update feature from main
git fetch origin
git rebase origin/main
Keeps the feature current.
12. Check rebase state
git status
Shows whether a rebase is in progress.
13. Rebase onto a remote
git rebase origin/main
Rebases onto the remote’s main directly.
14. Preserve merge commits
git rebase --rebase-merges main
Keeps merge structure during rebase.
15. Rebase a single commit
git rebase --onto main HEAD~1
Reapplies only the last commit.
Visual: Rebase Replays Commits
┌──────────────────────────────────────────────┐
│ Before rebase │
│ │
│ main: A ──► B ──► C ──► D │
│ \ │
│ feature: E ──► F ──► G │
│ │
├──────────────────────────────────────────────┤
│ Git computes the diff for E, F, G │
│ Rewinds to D │
│ Reapplies each diff │
│ │
├──────────────────────────────────────────────┤
│ After rebase │
│ │
│ main: A ──► B ──► C ──► D │
│ \ │
│ feature: E' ──► F' ──► G'│
│ │
│ New commits with new hashes │
│ │
└──────────────────────────────────────────────┘
Visual: Rebase vs Merge History
┌──────────────────────────────────────────────┐
│ Merge │
│ │
│ A ──► B ──► C ──► M │
│ \ / │
│ D ──► E │
│ │
│ Preserves branch structure │
│ Merge commit (M) │
│ │
└──────────────────────────────────────────────┘
┌──────────────────────────────────────────────┐
│ Rebase │
│ │
│ A ──► B ──► C ──► D' ──► E' │
│ │
│ Linear — no branches visible │
│ No merge commit │
│ │
└──────────────────────────────────────────────┘
Visual: Interactive Rebase
┌──────────────────────────────────────────────┐
│ git rebase -i HEAD~3 │
│ │
│ Editor opens: │
│ │
│ pick abc1234 Add login form │
│ squash def5678 Fix typo │
│ squash ghi9012 Fix again │
│ │
│ Save and close │
│ │
├──────────────────────────────────────────────┤
│ Result │
│ │
│ h8i9j0k (HEAD) Add login form (combined) │
│ │
│ One commit instead of three │
│ │
└──────────────────────────────────────────────┘
Visual: Safe Force Push
┌──────────────────────────────────────────────┐
│ git push --force │
│ │
│ Overwrites the remote │
│ No check for others' work │
│ ⚠️ Dangerous │
│ │
└──────────────────────────────────────────────┘
┌──────────────────────────────────────────────┐
│ git push --force-with-lease │
│ │
│ Checks that remote matches your last fetch │
│ Refuses if someone pushed │
│ ✅ Safer │
│ │
└──────────────────────────────────────────────┘
Visual: When to Rebase
┌──────────────────────────────────────────────┐
│ Rebase when: │
│ │
│ ✅ Branch is private │
│ ✅ You haven't pushed yet │
│ ✅ Single author │
│ ✅ Preparing to merge │
│ ✅ Cleaning up history │
│ │
├──────────────────────────────────────────────┤
│ Merge when: │
│ │
│ ✅ Branch is shared │
│ ✅ Others have pulled it │
│ ✅ Multiple authors │
│ ✅ Preserving merge history │
│ │
└──────────────────────────────────────────────┘
Summary
| Concept | Meaning |
|---|---|
| Rebase | Replay commits onto a new base |
| Merge | Combine branches with a merge commit |
| Interactive rebase | Edit, squash, reorder commits |
--force-with-lease | Safe force push |
--continue | Resume after conflict |
--abort | Cancel rebase |
--skip | Drop a commit |
| Rewrites history | New hashes, new commits |
Key takeaways:
- Rebase replays your commits onto a new base — a linear alternative to merge
- It rewrites history — new commits, new hashes
- Rebase for private branches, merge for shared ones — that’s the rule
git rebase mainupdates a feature branch with the latest maingit rebase -i HEAD~Nopens interactive mode — squash, reword, reorder, drop- Never rebase a branch others are working on — it breaks their local copies
- If you must push a rebased branch, use
--force-with-lease— never plain--force - Resolve conflicts during rebase and
--continue;--abortto cancel - Rebase gives cleaner history; merge gives more accurate history
- Use rebase before merging to keep main clean
- Always test after rebasing — the code changed
Remember: Rebase is about history — rewriting it to look cleaner. Merge is about records — preserving how things actually happened. Use rebase on your own branches to keep history tidy. Use merge on shared branches to avoid disrupting others. And if you ever push a rebased branch, use --force-with-lease, never plain --force.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!