ReadbackLesson 05In progress
2 steps · 30 minutes · one terminal

REBASE REPLAYS

Your agent says it “rebased onto main”. Nothing was moved: every commit it had was thrown away and rewritten, with new hashes, in a different order of events. Here is how to read the result — and why the conflict it stops on is labelled backwards.

What you already know

Retrieval · lessons 01 and 04

Before rebase, two things you have already proved. Answer both from memory — looking them up costs you the benefit.

Answer before you move on

You change the message of a commit that has four commits stacked on top of it. How many commit hashes change?

Answer before you move on

A three-way merge compares the two branch tips against a third commit. Which one?

Nothing moves

Claim + proof · git log main..feature

Everyone pictures rebase as picking up a branch and setting it down somewhere else. The picture is wrong in the way that matters, and the word encourages it: re-base, as though the base were a thing you could slide the branch along.

Here is a branch that has diverged. Two commits on feature, one on main, from a shared base.

Executed, output verbatimBefore
$ git log --graph --oneline --decorate --all
* 8af7f88 (main) Raise the timeout to 30s
| * fa08750 (HEAD -> feature) Add jitter
| * f96f7b8 Add exponential backoff
|/
* 009f9ef Add a timeout
* f1d9636 Add the API client

The classic fork. feature and main each have work the other does not.

Two range questions settle what a rebase is about to do. Both use the .. syntax from lesson 01: a..b means reachable from b but not from a.

Executed, output verbatim
$ git log --oneline main..feature
fa08750 Add jitter
f96f7b8 Add exponential backoff

Two commits. Each one will be applied separately, in this order, oldest first.

Executed, output verbatim
$ git log --oneline feature..main
8af7f88 Raise the timeout to 30s

One commit, and it touches the same file. That is the entire reason this rebase is about to stop.

Here is the part everyone has backwards

Rebase does not move your commits. It reads the diff each of your commits introduced, and applies those diffs one at a time on top of the new base, making a brand-new commit each time. Your original commits are not modified, not moved, and not deleted. They are abandoned, and a copy takes their place.

That is why the official description is “reapply commits on top of another base tip” (git-rebase) — reapply, not relocate. And it is why a rebase can conflict once per replayed commit: each one is a separate application onto a base it has never met.

Predict before you read on

The rebase is about to replay two commits onto main. Both of your commits touch client.ts, and so does main’s commit. How many separate conflicts can this rebase stop on, at most?

The merge you already understand

Each individual replay is the same three-way merge from lesson 04 — base, ours, theirs — run once per commit. Rebase adds no new merge machinery. It just runs the machinery you know, repeatedly, and commits the result each time.

Run this before any rebase you are supervising

git log --oneline <base>..<branch> lists exactly what will be replayed, and git log --oneline <branch>..<base> lists what it will be replayed onto. Neither command changes anything. If the first list is long, expect a long rebase.

3 of 5 steps remain

Ours is not yours

You have read the first 2 steps in full — a claim and the verification that settles it. The rest of this lesson, and the 9 lessons after it, open when subscriptions do. Nothing that is free today will be taken away then.

Read the free reference
Subscriptions open soon
the free preview stays