Last module ended with a fast-forward merge, the easy case where
main hadn't moved. In real life that rarely happens. Someone
else usually pushes to main while you're working on your
feature, and by the time you're ready to merge, both branches
have new commits.
That's called diverged history, and it needs a real merge.
The shape of a diverged merge
Picture the graph:
mainhas moved forward with commit A.- Meanwhile,
feature(which branched off before A) has moved forward with commit B. - Neither branch is an ancestor of the other. They share a common ancestor further back.
There's no straight line for Git to slide along. To combine them,
Git creates a new kind of commit: a merge commit. Merge
commits are special because they have two parents instead of
one. One parent points to main's tip, the other points to
feature's tip. That's how Git records "these two lines of
history joined here."
Every other commit in your history has exactly one parent (or zero, for the very first commit). Merge commits are the only ones with two.
The command is the same
You use git merge exactly like before:
git switch main
git merge feature
Git sees that a fast-forward isn't possible, so it does the real work: it walks back to the common ancestor, compares what each branch changed, and combines those changes into a new snapshot. If the two branches changed different files (or different lines of the same file), Git combines them automatically. You get:
Merge made by the 'ort' strategy.
feature.txt | 1 +
1 file changed, 1 insertion(+)
Now main sits at a brand new commit whose two parents are the
previous main and feature. Both branches' work is in it.
The commit message
By default, Git opens your editor and pre-fills a message like
Merge branch 'feature'. You can accept it or edit it. If you
want to skip the editor:
git merge feature -m "Merge feature into main"
Or git merge --no-edit feature to accept the default without
opening the editor.
Reading the graph
After the merge, run:
git log --oneline --all --graph
You'll see a diamond shape: two lines splitting off from a common point and rejoining at the merge commit. That diamond is the visual signature of a diverged merge. Once you can read it, you can read most Git history.
When two branches conflict
The example above assumes Git could figure out the combination on its own. What if both branches modified the same line of the same file, in different ways? Then Git can't decide which version to keep. That's a merge conflict, and that's the next lesson.