Rebase is one of Git’s most powerful and most misunderstood commands. In this lesson you will see exactly what rebasing does, rebase a feature branch, handle conflicts, compare rebase with merge and learn the golden rule that keeps teams safe.
📖 What You’ll Learn: how rebase replays commits, rebasing a feature branch on main, continue, skip and abort, rebase vs merge, the golden rule and force-with-lease, pull –rebase, useful variations like –onto and –autostash, and undoing a rebase with reflog.
🧬 What Does git rebase Do?
git rebase moves a branch so that it starts from a different commit, usually the latest main. Git takes your branch’s commits, sets them aside, updates the base, and replays your commits one by one on top.
Before: After: git switch feature && git rebase main
C3 ── C4 ← feature C3' ── C4' ← feature
/ /
C1 ── C2 ── C5 ── C6 ← main C1 ── C2 ── C5 ── C6 ← main
The replayed commits (C3', C4') have the same changes but new hashes, because their parent changed. The result is a straight, linear history, as if you had started your work after C6.
▶️ Rebasing Step by Step
git switch feature/login-tests
git fetch
git rebase origin/main # or: git rebase main (after updating main)
Successfully rebased and updated refs/heads/feature/login-tests.
Then fast-forward main (or open a pull request):
git switch main
git merge feature/login-tests # a fast-forward: no merge commit needed
🧯 Conflicts During a Rebase
Because commits are replayed one at a time, you may resolve conflicts for each commit:
git rebase main
# CONFLICT (content): Merge conflict in tests/login.spec.ts
# fix the file, then:
git add tests/login.spec.ts
git rebase --continue
| Command | What it does |
|---|---|
git rebase --continue | Continue after resolving the current commit’s conflicts |
git rebase --skip | Drop the current commit and continue |
git rebase --abort | Stop and return to the state before the rebase |
How to resolve the conflict itself is explained in Resolve Merge Conflicts.
⚖️ Rebase vs Merge
git merge | git rebase | |
|---|---|---|
| History | Preserved exactly, with merge commits | Rewritten into a straight line |
| Commit hashes | Unchanged | New hashes for rebased commits |
| Merge commits | Yes (unless fast-forward) | No |
| Conflict resolution | Once, for the whole merge | Possibly once per replayed commit |
| Safe on shared, pushed branches | ✅ Yes | ❌ Not without coordination |
| Reading history | Shows when branches were integrated | Clean and easy to follow |
| Typical use | Integrating finished features into main | Updating your own feature branch with main |
A common team approach: rebase your own feature branch on main to keep it up to date and clean, then merge it into main through a pull request.
⚠️ The Golden Rule of Rebasing
⚠️ Common mistake: Do not rebase commits that other people have based work on. Rebasing changes commit hashes; teammates who pulled the old commits will get duplicated commits and confusing conflicts. Rebase only local commits or branches that only you use.
If you rebase a branch you already pushed (your own feature branch), the remote rejects a normal push. Update it safely:
git push --force-with-lease
🔁 Pull with Rebase
Instead of creating “Merge branch ‘main’ of github.com…” commits every time you pull, replay your local commits on top of the remote:
git pull --rebase
git config --global pull.rebase true # make it the default (optional)
🛠️ Useful Variations
git rebase -i HEAD~3 # interactive: squash, reword, reorder (next module)
git rebase --onto main old-base feature # move a branch to a new base, skipping old-base's commits
git rebase main --autostash # stash uncommitted changes automatically during the rebase
Interactive rebase gets its own lesson in Advanced Git.
🛟 Undo a Rebase
If a rebase went wrong after it finished, find the branch’s previous position in the reflog and reset to it:
git reflog
# a1b2c3d HEAD@{5}: checkout: moving from main to feature/login-tests
git reset --hard HEAD@{5}
More in git reflog.
📝 Assignment
- Create
feature/rebase-demofrommainand make two commits. Make one commit onmain. - Rebase the feature branch onto
mainand comparegit log --oneline --graph --allbefore and after. Note the changed hashes. - Fast-forward
mainto the rebased branch. - Repeat, creating a conflict on purpose, and resolve it with
git rebase --continue. - Start another rebase and cancel it with
git rebase --abort. - Push a feature branch, rebase it, and update the remote with
--force-with-lease.
❓ FAQ
🤔 What does git rebase do?
It replays the commits of your branch on top of another branch (or commit), giving them a new base and new hashes, which produces a linear history.
🤔 What is the difference between git merge and git rebase?
Merge combines branches and keeps history as it happened, with merge commits. Rebase rewrites your branch’s commits on top of the target, creating a straight history without merge commits.
🤔 When should I not use git rebase?
Do not rebase commits that are on a shared branch others are using, such as main or a branch your teammates pulled.
🤔 How do I abort a rebase?
git rebase --abort returns everything to how it was before the rebase started.
🤔 Why do I need to force push after a rebase?
Rebasing changes commit hashes, so the remote branch no longer matches. Use git push --force-with-lease for your own branch.
🎯 Next Steps
- 📦 git stash: Save Work in Progress
- 🍒 git cherry-pick: Copy Commits Between Branches
- 📘 Git and GitHub Tutorial: full course
🎬 Learn Git and GitHub step by step: watch the series on YouTube!
Subscribe to SqaToolsByDY • Practice on sqatools.in
4 thoughts on “git rebase Explained: Rebase vs Merge, Conflicts and the Golden Rule”