ReadbackLesson 07In progress
2 steps · 28 minutes · one terminal

THREE WAYSTO LAND

The green button on a pull request has a dropdown, and the three options produce identical files and three completely different histories. Your agent picks whichever the repository defaults to. Here is how to choose it deliberately, once, and what the squash option quietly costs.

What you already know

Retrieval · lessons 04 and 05

Two from memory. Both are load-bearing for the decision at the end.

Answer before you move on

What makes a merge commit different from every other commit?

Answer before you move on

A rebase replays three commits. How many of the three get new hashes?

One branch, three histories

Claim + proof · three clones

Here is a branch of the shape an agent actually produces: three commits, one of which is a fixup for a typo it made two commits earlier. Meanwhile main moved on.

Executed, output verbatimBefore
$ git log --graph --oneline --decorate --all
* 27553c3 (HEAD -> main) Note the log level
| * a8648d0 (feature) Add jitter
| * 480c76f Fix a typo in the backoff constant
| * 232f0b8 Add exponential backoff
|/
* 82636c0 Add a timeout
* d1ae31c Add the API client

“Fix a typo in the backoff constant” is the commit nobody wants in main forever. It is also the whole argument for squashing.

Three identical copies of that repository, and each one lands the branch a different way. GitHub calls them merge commit, squash and merge, and rebase and merge (GitHub docs); each maps onto a plain git command you already know.

Merge commitgit merge --no-ff feature.

Executed, output verbatim1 of 3
$ git log --graph --oneline --decorate --all
*   ebce595 (HEAD -> main) Merge branch 'feature'
|\
| * a8648d0 (feature) Add jitter
| * 480c76f Fix a typo in the backoff constant
| * 232f0b8 Add exponential backoff
* | 27553c3 Note the log level
|/
* 82636c0 Add a timeout
* d1ae31c Add the API client

Every original commit survives, with its own hash, and a new commit records that the two lines joined. The fixup is in main forever.

Squashgit merge --squash feature, then one commit.

Executed, output verbatim2 of 3
$ git log --graph --oneline --decorate --all
* daefc52 (HEAD -> main) Add exponential backoff and jitter (#42)
* 27553c3 Note the log level
| * a8648d0 (feature) Add jitter
| * 480c76f Fix a typo in the backoff constant
| * 232f0b8 Add exponential backoff
|/
* 82636c0 Add a timeout
* d1ae31c Add the API client

One new commit on main, with no link to the branch at all. The three originals are still sitting on feature, untouched and unreferenced by main.

Rebase-mergegit rebase main on the branch, then a fast-forward.

Executed, output verbatim3 of 3
$ git log --graph --oneline --decorate --all
* 3e51c0b (HEAD -> main, feature) Add jitter
* 8a9a98d Fix a typo in the backoff constant
* 3ea4a0e Add exponential backoff
* 27553c3 Note the log level
* 82636c0 Add a timeout
* d1ae31c Add the API client

Perfectly linear, and every commit preserved — but every one of them rewritten. 3ea4a0e is a new object; the original 232f0b8 is abandoned.

The part that makes this a real decision

All three produce byte-identical files. Checked out, the three repositories above are indistinguishable. What differs is only the history — and history is not decoration, it is the thing you read when something breaks at 2am.

Check it on any repository

git log --graph --oneline --decorate on a project you did not write tells you which method it uses within seconds: diamonds mean merge commits, a flat line with “(#123)” suffixes means squash, a flat line with ordinary messages means rebase-merge.

3 of 5 steps remain

What each one costs

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