Merging and Conflicts
When a Merge Needs a Commit
A fast-forward works when one
Two lines need a join
Imagine both branches started at B. main then made commit C, while simplify-tiers made commit D:
C main
/
A -> B
\
D simplify-tiers
Moving main directly to D would drop C from its line. Moving it nowhere would leave out D. Git instead creates a new commit that joins the two histories:
C ----\
/ M main
A -> B /
\ /
D --- simplify-tiers
The new commit M is a merge commit. An ordinary commit has one parent, the commit immediately before it. A true merge commit has two parents: the previous tip of the current branch and the tip of the branch that was brought in.
The order carries the direction. If main is current, its previous tip is the first parent. The tip of simplify-tiers is the second. Both remain part of the reachable history, so the merge does not discard either line of work.
A merge commit is still a snapshot
The merge commit records one complete project snapshot, just like every other commit. Its difference is not a special kind of file storage. Its difference is the two parent links that say, “these two lines meet here.”
When the branches changed different files, or different parts of one file, Git can usually build that snapshot without help. It combines the changes and creates the merge commit.
When both branches changed the same lines differently, Git cannot know which final text you intend. It stops before the commit and asks you to decide. That stop is a
What makes a true merge commit different from an ordinary commit?
Both branches changed the same lines differently. What does Git do when it cannot choose the intended result?
The prepared