Skip to content
Commitpedia
Log in Join & edit

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?

Edit history of Merging vs rebasing in Git: 1 recorded edit
Edit history · 1 edit
Type
Article
Edits
1
Editors
1
First issued
15 Oct 2026
Last edit
15 Oct 2026
Reading
2 min

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

History

Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.

  1. Commitpedia +3,154 chars

Report a problem

Something wrong, unsafe or copied? Tell the editors.
What is wrong?