Rebasing Branches
Reviewed & published by Brayan K
Rebase is Git's tool for a clean, linear history — and one of the most misunderstood. By the end of this lesson you'll know how rebase differs from merge, how to replay your feature branch onto main, how to handle conflicts mid-rebase, and the one golden rule that keeps it safe.
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
- How rebase replays commits onto a new base
- The difference between rebase (linear) and merge (merge commit)
- Rebase a feature branch onto main with git rebase main
- Why rebasing rewrites commits into new hashes
- Handle conflicts with --continue and bail with --abort
- The golden rule: never rebase shared, pushed commits
1️⃣ Rebase vs Merge
Both merge and rebase integrate one branch into another, but they leave different histories. Merge preserves both lines and may add a two-parent merge commit. Rebase replays your commits on top of the target's tip as new commits, producing a single linear line with no merge commit. Same end result in your files, very different-looking history.
# MERGE and REBASE both integrate one branch into another, but the
# history they leave behind is different.
#
# Start: main moved on AND your feature has its own commits
#
# A---B---C main
# \
# D---E feature
#
# MERGE (git switch main; git merge feature) keeps both lines and adds a
# merge commit M with two parents:
#
# A---B---C-------M main
# \ /
# D---E---/ feature
#
# REBASE (git switch feature; git rebase main) REPLAYS D and E on top of
# C as brand-new commits D' and E', giving a straight line:
#
# A---B---C---D'---E' feature (linear, no merge commit)2️⃣ Rebasing a Feature onto main
The everyday use of rebase: keep your feature branch current. Switch to the feature branch and run git rebase main. Git replays your commits on top of main's latest tip, rewriting them with new hashes. The result is a tidy, linear history — and a later merge into main can often fast-forward.
# Replay your feature branch onto the latest main.
# 1) Make sure main is up to date (in a real project: git switch main; git pull)
# 2) Switch to your feature branch
git switch feature
# 3) Rebase it onto main — D and E become new commits on top of main's tip
git rebase main
# The commits are REWRITTEN (new hashes), and history is now linear.
git log --oneline --graph --all3️⃣ Handling Conflicts Mid-Rebase
Because rebase replays commits one at a time, a conflict can pause it partway. Fix the conflict markers in the file, stage it with git add, then run git rebase --continue — not git commit. If you'd rather give up entirely, git rebase --abort returns the branch to exactly where it started.
# A rebase replays commits one by one, so a conflict can stop it midway.
git rebase main
# CONFLICT (content): Merge conflict in app.js
# 1) Open the file, fix the conflict markers (<<<<<<<, =======, >>>>>>>)
# 2) Stage the resolved file
git add app.js
# 3) Continue the rebase (do NOT run git commit here)
git rebase --continue
# Changed your mind mid-rebase? Bail out and return to the start:
git rebase --abort4️⃣ The Golden Rule
Never rebase commits you've already pushed and shared. Rebasing rewrites those commits into new ones with different hashes, so anyone who already pulled the originals ends up with a diverged history and painful conflicts. The safe pattern: rebase your own local, unpushed branches; use merge for anything public.
# 🏆 THE GOLDEN RULE OF REBASING:
# Never rebase commits that you have already pushed and shared.
#
# Rebasing REWRITES commits (new hashes). If teammates already pulled the
# old commits, your rewritten branch no longer matches theirs.
# ✅ SAFE — your own LOCAL, unpushed feature branch:
git switch feature
git rebase main
# ❌ DANGEROUS — a branch others have pulled, or the public main:
# git switch main
# git rebase feature # rewrites shared history — don't
# Rule of thumb: rebase private work, MERGE public work.Your turn. Bring a feature branch up to date on top of main. Fill in the two blanks.
# 🎯 YOUR TURN — replace each ___ then run it in your terminal.
# Goal: bring your feature branch up to date on top of main, linearly.
# 1) Switch to your feature branch
git switch ___ # 👉 your feature branch's name
# 2) Replay its commits on top of the latest main
git ___ main # 👉 the command that replays commits
# 3) Confirm the history is now a straight line
git log --oneline --graph --all
# ✅ Expected: "Successfully rebased ..." and a single straight line of
# commits with feature sitting directly on top of main.Common Errors (and the fix)
- Ran git commit during a conflict: mid-rebase you use git add then git rebase --continue, not git commit.
- Rebased a pushed branch and push is rejected: you rewrote shared history. Prefer merge for public branches; only force-push private ones with --force-with-lease.
- Lost track mid-rebase: git rebase --abort always returns you to the pre-rebase state.
- Same conflict repeats on each commit: that's normal when many commits touch the same lines — resolve and --continue through each.
Pro Tips
- 💡 Rebase private, merge public: the simplest rule that keeps you safe.
- 💡 Update before you merge: rebase your feature onto the latest main so the merge is clean.
- 💡 --abort is your undo: a rebase is always reversible until it finishes.
- 💡 Commit small: smaller commits mean smaller, easier-to-resolve rebase conflicts.
📋 Quick Reference
| Command | Purpose |
|---|---|
| git rebase main | Replay current branch onto main |
| git rebase --continue | Proceed after resolving a conflict |
| git rebase --abort | Cancel and restore the pre-rebase state |
| git rebase --skip | Skip the current conflicting commit |
| git log --oneline --graph --all | Confirm the resulting history shape |
Mini-Challenge: Straighten a Diverged Branch
No commands given this time — just the plan. Diverge two branches, then rebase to make the history linear.
# 🎯 MINI-CHALLENGE: clean up a diverged feature branch.
# No commands given — just the plan. Run each step in your terminal.
#
# 1. From main, create feature and make 2 commits on it
# 2. Switch back to main and make 1 commit there (now they've diverged)
# 3. Draw the graph — confirm the branches forked
# 4. Switch to feature and rebase it onto main
# 5. Draw the graph again — confirm it's now ONE straight line
#
# ✅ Expected: after the rebase, "git log --oneline --graph --all" shows a
# single linear history with feature on top of main.
# your commands here🎉 Lesson Complete!
- ✅ Rebase replays your commits onto a new base for a linear history
- ✅ Merge can add a merge commit; rebase rewrites commits into new hashes
- ✅ git rebase main updates a feature branch onto the latest main
- ✅ Resolve conflicts then --continue; bail with --abort
- ✅ Golden rule: never rebase commits you've already pushed/shared
Practice quiz
What does git rebase do?
- Deletes a branch
- Merges two branches with a merge commit
- Replays your commits on top of another branch's tip
- Pushes to the remote
Answer: Replays your commits on top of another branch's tip. Rebase moves your branch's commits so they sit on top of the target branch.
How does rebase differ from merge in the history it produces?
- Rebase produces a LINEAR history; merge can add a merge commit
- Rebase adds a merge commit; merge stays linear
- They produce identical history
- Rebase deletes history
Answer: Rebase produces a LINEAR history; merge can add a merge commit. Rebase rewrites commits onto a new base for a straight line; merge may create a two-parent merge commit.
To replay your feature branch onto the latest main, you run...
- git rebase feature (while on main)
- git merge --rebase
- git reset main
- git rebase main (while on feature)
Answer: git rebase main (while on feature). From your feature branch, git rebase main replays feature's commits on top of main.
Do rebased commits keep their original hashes?
- Yes, always
- No — they're rewritten, so they get new hashes
- Only the first one changes
- Only on the remote
Answer: No — they're rewritten, so they get new hashes. Rebase creates new commits with new hashes because their base (parent) changed.
What is the GOLDEN RULE of rebasing?
- Never rebase commits you've already pushed/shared
- Always rebase main
- Rebase before every commit
- Rebase only on Fridays
Answer: Never rebase commits you've already pushed/shared. Rebasing rewrites history, which breaks collaborators who already have those commits.
Why does rebasing shared commits cause problems?
- It's slow
- It deletes files
- Teammates' history diverges from your rewritten commits
- It can't be pushed at all
Answer: Teammates' history diverges from your rewritten commits. Others still have the old commits; your new hashes no longer match, causing conflicts.
A good use of rebase is...
- Rebasing the public main branch
- Updating your LOCAL feature branch onto the latest main before merging
- Rebasing a teammate's branch
- Rebasing every release tag
Answer: Updating your LOCAL feature branch onto the latest main before merging. Rebasing your own unpushed feature branch onto main gives a clean, up-to-date history.
If a rebase hits a conflict, which command continues after you fix it?
- git rebase --skip-all
- git merge --continue
- git commit --rebase
- git rebase --continue
Answer: git rebase --continue. After resolving and staging the conflict, git rebase --continue proceeds.
How do you abandon a rebase and return to where you started?
- git reset --hard
- git rebase --abort
- git rebase --undo
- Ctrl+C only
Answer: git rebase --abort. git rebase --abort restores the branch to its pre-rebase state.
After a successful `git rebase main` on feature, what often happens on main?
- main is deleted
- main rewinds
- A later git merge of feature into main can fast-forward (linear)
- Nothing can be merged
Answer: A later git merge of feature into main can fast-forward (linear). Because feature now sits directly on top of main, merging it can fast-forward cleanly.
Continue this course
- Previous: Tagging Releases
- Next: Interactive Rebase: squash, edit, reorder — Clean up history with git rebase -i — squash, fixup, reword, and edit
- Quick reference: Git cheat sheet › Rebase & Cherry-pick
Frequently asked questions
What is the difference between rebase and merge?
Both combine work from two branches. Merge keeps both lines of history intact and, when they've diverged, records a merge commit with two parents — an honest record of when things came together. Rebase instead replays your branch's commits on top of the target branch's tip, rewriting them as new commits to produce a single straight line. Merge preserves history exactly; rebase rewrites it for cleanliness.
Does rebasing lose my commits?
No — your commits' changes are preserved, but the commits themselves are rewritten with new hashes because their parent (base) changed. So you keep all your work; what changes is the commits' identity and position in history. If a rebase ever goes wrong, git rebase --abort returns you to exactly where you started, and git reflog can recover the originals.
What's the golden rule of rebasing?
Never rebase commits you've already pushed and shared. Rebasing rewrites those commits into new ones with different hashes, so any teammate who already pulled the originals now has a history that diverges from yours, causing painful conflicts. The safe pattern is: rebase your own local, unpushed branches; use merge for anything already public.
A rebase stopped with a conflict — what do I do?
Rebase applies your commits one at a time, so a conflict pauses the process. Open the conflicted file, resolve the <<<<<<< / ======= / >>>>>>> markers, then stage it with git add. Crucially, don't run git commit — instead run git rebase --continue to move on to the next commit. If you'd rather give up, git rebase --abort restores the branch to its pre-rebase state.
When should I rebase instead of merge?
Rebase shines for keeping a local feature branch current: before merging your feature into main, rebase it onto the latest main so your work sits cleanly on top and the eventual merge can fast-forward. Use merge when integrating shared branches or when you want history to faithfully record that two lines of work came together. A common team policy is rebase locally, merge to share.