Rebase

Replay your work on top of someone else’s, and know exactly when that is a bad idea.

10of 16
≈ 13Min read
5Parts

What rebase does

Git takes every commit that is on your branch and not on main, and applies them one at a time on top of main. The changes are the same; the commits are new objects with new ids, because a commit id includes its parent.

The result is a straight line: it looks as though you started your branch this morning, from the latest main.

the same work, starting from a later point
before                          after: git switch feature; git rebase main

A ── B ── C   (main)            A ── B ── C   (main)
     \                                      \
      D ── E  (feature)                      D' ── E'  (feature)

The two ways to catch up

Merging records the truth: you branched at B and caught up later. Rebasing produces a history that is easier to read: one clean line of your commits, each of which can be reviewed and reverted on its own. Both are legitimate; teams pick one and write it down.

same goal, different history
git switch feature
git merge main        # a merge commit appears in your branch
git rebase main       # your commits move on top of main instead

The one rule

The practical version: rebase a branch only you are working on, as often as you like. Once you have opened a pull request that others are reviewing, prefer merges — or warn them before you force-push.

Never rebase commits other people have

Rebasing replaces commits with new ones. Anyone who already pulled the old ids now has commits that no longer exist in your branch, and their next pull produces duplicates or a mess. Rebase your own unpushed work freely; leave shared history alone.

When it stops

a rebase can conflict once per commit
git rebase main
# CONFLICT in price-list.md

# fix the file, then
git add price-list.md
git rebase --continue

git rebase --skip      # drop this commit
git rebase --abort     # put everything back
ours and theirs are the other way round

During a rebase your commits are being replayed onto main, so "ours" is main and "theirs" is your own commit. Read the file, not the labels.

The pull that is really a rebase

A plain git pull that finds new commits makes a merge commit, and a busy repository fills up with "Merge branch 'main' of github.com…" noise. --rebase replays your local commits on top instead — which is almost always what you meant.

avoid the "Merge branch main into main" commits
git pull --rebase                       # once
git config --global pull.rebase true    # for good

Practice