Merging

Bring two lines of work together, and read the shape of the history you just made.

08of 16
≈ 12Min read
5Parts

Fast-forward: nothing to merge

If the branch you are merging already contains everything on your branch, there is nothing to combine: git moves the pointer forward. No merge commit, no new object. This is the common case for a small branch merged the same afternoon.

main has not moved, so the pointer just slides along
main:     A ── B
                   \
feature:            C ── D        (main is an ancestor of feature)

$ git switch main
$ git merge feature
Updating b303b73..e184a0e
Fast-forward

The merge base

When both branches have moved, git finds the merge base — the most recent commit they share — and compares each side against it. A file only one side changed takes that side. A file both sides changed the same way is already agreed. A file both sides changed differently is a conflict, and that is the next lesson.

you can ask for it
git merge-base main feature

The merge commit

Two parents, in order: the branch you were on, then the branch you merged. That order is what HEAD^1 and HEAD^2 mean, and what git revert -m 1 needs if the merge has to come back out.

the only commit with two parents
$ git merge feature
Merge made by the 'ort' strategy.

$ git log --oneline --graph
*   5d9fd3e (HEAD -> main) Merge branch 'feature'
|\
| * e184a0e (feature) Add the fitting notes
* | 9ec51e0 Update the price list
|/
* b303b73 Start the notes

--no-ff, and why teams use it

A merge commit records that these commits were one piece of work, keeps the branch name in the message, and can be reverted in one move. The cost is a busier graph. Most teams that use pull requests get --no-ff behaviour by default, which is why main looks like a ladder of merges.

force a merge commit even when a fast-forward was possible
git merge --no-ff feature

Merge or rebase?

A reasonable default: rebase your own branch onto the latest main while you work, then merge it in. The next lesson but one is rebase in full.

MergeRebase
Historytrue: it records what happenedtidy: as if you had started later
Commit idsunchangedall new
Shared branchesalways safenever do it
Conflictsonce, at the endpossibly once per commit

Practice