Great work!

XP to next level

BugEater
EN

Two Ways to Catch Up: Merge vs. Rebase

Learning Objectives

By the end of this lesson you will be able to:

  • Describe what git merge and git rebase each do to the commit graph
  • Explain why rebase changes commit IDs and merge does not
  • Read a linear history and a merge-shaped history and say which command produced it
  • Name the trade-off each one makes, in one sentence

The Situation

You cut test/PAY-4417 from main on Monday. It is now Thursday, main has eleven new commits, and you need them — a dependency was upgraded and your branch will not build without it.

          A───B───C   test/PAY-4417
         /
D───E───F───G───H     main

A, B, C are yours. G and H arrived after you branched. Both commands below get G and H into your branch. They produce different repositories.

Option 1: git merge main

git switch test/PAY-4417
git merge main

Git finds the common ancestor (F), takes both sets of changes, combines them, and records the result as a new commit with two parents:

          A───B───C───M   test/PAY-4417
         /           /
D───E───F───G───────H     main

M is the merge commit. Its existence is the point: it is a permanent record that two lines of development met here, on this date, resolving these conflicts.

Nothing that already existed was changed. A, B and C still have the IDs they had on Monday. Anyone who pulled your branch earlier still has a valid, consistent copy.

Option 2: git rebase main

git switch test/PAY-4417
git rebase main

Read the name literally: it changes the base of your branch. Git takes the changes introduced by A, B, C, sets your branch aside, moves to the tip of main, and replays them one at a time:

D───E───F───G───H───A'───B'───C'   test/PAY-4417
                │
                main

The history now claims you started from H. There is no merge commit and no fork in the graph — one straight line.

The Detail That Matters: New IDs

Look at the apostrophes. A' is not A.

A commit's ID is a hash of its content and its parent. Replaying A onto a different parent necessarily produces a different hash. A contained the same diff and the same message, but A' is a new object.

A, B and C still exist in the object database for a while, but nothing points at them any more. As far as the branch is concerned they are gone, replaced by copies.

This one fact is the source of everything else in this module:

  • It is why rebase gives you a clean line — the old commits are not preserved, only their changes are.
  • It is why rebase is dangerous on a shared branch — a colleague's clone still points at A, B and C, which your branch no longer contains.
  • It is why a rebased branch needs a force-push, which you will meet in Lesson 2.

Which History Do You Want?

git merge git rebase
Graph shape Branching, with merge commits One straight line
Existing commits Untouched Replaced by copies with new IDs
Records that a branch existed Yes, permanently No
Safe on a shared branch Yes No
Conflicts Resolved once, in one merge Possibly once per replayed commit
Push afterwards Normal push Force-push required

Neither column is the correct one. Teams pick a convention and stick to it, and most land somewhere in the middle: rebase your own feature branch to keep it current and tidy, merge it into main at the end so the merge point is recorded.

Why a Tester Should Care

Two very concrete reasons.

Reading history. When a regression appears and you are trying to establish when it landed, a linear history reads top to bottom in date order. A history with fifty merge commits from twelve branches does not, and git log without --graph can list commits in an order that looks like nonsense. In Module 6, git bisect also behaves far more predictably on a mostly linear history.

Pulling a rebased branch. If a developer rebases a branch you have already checked out, your next git pull will try to merge the old commits with their new copies and produce a mess of duplicates and conflicts. Recognising "this branch was rebased" means you reset to the remote version instead of merging — and you will do exactly that in Lesson 3.

Pro Tip: git log --oneline --graph --all is the fastest way to see which convention a repository actually follows. If the picture is a straight line, the team rebases. If it looks like a railway junction, it merges.

Key Takeaways

  • merge combines two lines and records the meeting as a commit with two parents
  • rebase replays your commits on top of another branch, producing a straight line
  • Replayed commits get new IDs — they are copies, not the originals
  • Merge preserves history exactly; rebase produces a cleaner history by discarding the original commits
  • Rebasing is safe on your own unshared branch and dangerous on a shared one
  • A linear history is significantly easier to read, bisect and reason about

Quiz

What does git rebase main do to the commits on your branch?

After a merge, what identifies the merge commit in the graph?

Why is rebasing a branch that a colleague has already pulled a problem?

You run git log --oneline --graph --all and see one straight line with no forks. What can you conclude?