Merging vs rebasing in Git
Merge and rebase both bring commits from one branch into another. Merge keeps history exactly as it happened; rebase replays your commits on top so history reads as a straight line.
Not checked by a trusted editor yet Last edited Outdated?
You branched off main to build a feature, and meanwhile someone else pushed to main. Your branch and main have now diverged. There are two ways to combine them.
Merge: join the two lines
git switch main
git merge feature/login
Git finds the last commit both branches share, combines the changes since then, and records a merge commit with two parents. Nothing existing is changed, so merging is always safe on shared branches. The cost is a history with many forks and joins.
If main has not moved since you branched, Git simply moves main forward to your commit (a fast-forward) and makes no merge commit. Use git merge --no-ff if you want a merge commit anyway, for example to keep a record that a feature landed as a unit.
Rebase: replay your commits on the new tip
git switch feature/login
git rebase main
Rebase takes the commits that exist only on your branch, sets them aside, moves the branch to the tip of main, and re-applies them one by one. The result looks as if you had started your work today. Because each commit is re-created, the commits get new hashes.
git log --oneline --graph --all
Run that before and after each option on a test repository; seeing the graph change is the fastest way to understand the difference.
The one rule for rebasing
Do not rebase commits that other people have already based work on, such as anything on a shared main. Their copies would still point at the old hashes, and the next pull would bring both versions back.
Rebasing your own feature branch after pushing it is common. The remote will then reject a normal push, because the history no longer lines up. Use:
git push --force-with-lease
--force-with-lease overwrites the remote branch only if it still points where you last saw it. If a teammate pushed in the meantime, the push is rejected with stale info instead of silently deleting their commits, which is exactly what plain --force would do.
Interactive rebase: tidy up before review
git rebase -i opens a to-do list of your commits in your editor. Change the word in front of a commit to decide what happens to it:
pick 8055539 Add login form
fixup 113068a fix typo
squash c87db2e wip
pick: keep as is.reword: keep, but edit the message.squash: fold into the commit above and combine the messages.fixup: fold in and discard this message.drop(or delete the line): remove the commit. Reordering lines reorders commits.
A handy pattern is to mark small corrections as you go and let Git place them:
git add login.py
git commit --fixup=HEAD~2
git rebase -i --autosquash main
When a rebase stops on a conflict
Fix the file, then git add it and run git rebase --continue. git rebase --skip drops the commit that conflicts, and git rebase --abort puts everything back as it was before you started.
Which should you use?
Follow your team’s convention. A common split is: rebase your own branch onto main to keep it current, and let the pull request merge it into main. On GitHub the merge button offers Create a merge commit, Squash and merge, and Rebase and merge, and repository admins can turn each one on or off.
See also
- 0041 Fix: CONFLICT (content): Merge conflict in … Two branches changed the same lines and Git cannot choose for you. Open the file, keep the right text, remove the markers,… Intermediate · Fix · Any system Article Branching & rebasing · Common errors 15 Oct 2026
- 0262 Make your first pull request: Git and GitHub from first commit to merged change A complete beginner's path through Git and GitHub: set up Git, make commits, ignore files, use branches, push to GitHub, open a… Beginner · Tutorial · Any system Article Branching & rebasing · Pull requests · Setup 15 Oct 2026
History
Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.
- Commitpedia +3,154 chars