What is the difference between git merge and git rebase?
Both bring changes from one branch into another. Merge joins the two histories with a new merge commit and keeps everything as it happened. Rebase replays your commits on top of the other branch, giving a straight, linear history but rewriting commit IDs. Never rebase commits that others have already pulled.
Explain it simply
Say you made a feature/login branch from main on Monday. By Wednesday, your teammates have added new commits to main. You now need their changes in your branch.
- Merge says: "Take both lines of work and tie them together with a knot." Git creates a new merge commit with two parents. Nothing old is changed.
- Rebase says: "Pretend I started my work today." Git lifts your commits off, moves your branch to the latest
main, and replays your commits one by one on top. The history looks like a straight line.
Merge is honest about what happened. Rebase is tidier to read.
Example
Starting point:
A---B feature/login
/
C---D---E---F mainMerge main into the feature branch:
git switch feature/login
git merge main A---B---M feature/login
/ /
C---D---E---F mainM is the merge commit.
Rebase the feature branch onto main:
git switch feature/login
git rebase main A'--B' feature/login
/
C---D---E---F mainA' and B' contain the same changes as A and B, but they are new commits with new IDs.
How it works
Merge finds the common ancestor (D), combines the changes from both sides, and records the result in one commit. If there are conflicts, you fix them once.
Rebase saves your commits as patches, resets your branch to the tip of main, then applies each patch in order. If there are conflicts, you may fix them once per commit, running git rebase --continue after each. git rebase --abort takes you back to where you started.
Real-world use
- Many teams rebase their own local feature branch on the latest
mainbefore opening a pull request, so the review shows a clean set of commits. git pull --rebaseavoids the extra "Merge branch 'main' of ..." commits that clutter history.- Teams that want to see exactly when a feature landed prefer merge commits on
main. - GitHub's "Squash and merge" and "Rebase and merge" buttons are just these ideas applied at the end of a pull request.
Common mistakes
- Rebasing a shared branch. This is the golden rule: do not rebase commits that you have already pushed and someone else may have pulled. Their copy still has the old commit IDs, and the histories split into duplicates and confusion.
- Using
git push --forceafter a rebase without checking. Usegit push --force-with-lease, which refuses to push if someone else updated the remote branch in the meantime. - Panicking in the middle of a rebase. Run
git status; it tells you exactly which step you are on and what to do.
What to say in the interview
"Both integrate changes from one branch into another. Merge creates a merge commit with two parents and preserves the true history, so it is safe on shared branches. Rebase replays my commits on top of the target branch, which gives a linear history but creates new commit hashes. The golden rule is never rebase public history that others have pulled. In practice I rebase my local feature branch onto main to keep it clean, and merge into main through a pull request."
Follow-up questions
- What is a fast-forward merge?
- What does
git rebase -ido? - Why is
--force-with-leasesafer than--force? - How would you recover if a rebase went wrong?
Go deeper
Read these once the basics above feel easy.
Interactive rebase lets you clean up your own commits before sharing them:
git rebase -i HEAD~3Git opens an editor listing the last three commits. Change pick to squash (or s) to fold a commit into the one above it, reword to edit a message, or drop to remove it. This is how you turn "fix", "fix again" and "final fix" into one meaningful commit.
If a rebase goes badly, the old commits are not gone yet. git reflog lists where HEAD has pointed recently, for example HEAD@{5}. You can return with git reset --hard HEAD@{5}. Unreachable commits are kept for a while (by default around 30 to 90 days) before garbage collection removes them.