Git Merging
Merging is how two independent histories become one. Git does it by finding where the histories last agreed — the merge base — working out what each side changed since then, and combining both sets of changes.
That mechanism is worth understanding precisely, because almost every confusing merge outcome follows from it: why some merges produce a commit and others do not, why conflicts appear where they do, and why two changes can merge cleanly and still be wrong together.
Start with Git Merge ExplainedMerging is a three-way comparison
Section titled “Merging is a three-way comparison”The word “merge” suggests combining two things. Git actually compares three.
A trunk lane labelled main with commits A, B, C and a merge commit M. A branch lane labelled feature leaves main after commit B with commits X and Y, merging into M. Commit B is highlighted as the merge base — the most recent commit reachable from both tips.
Given the base B and the two tips C and Y, Git asks, for each region of each file:
- Did only one side change it? Take that change.
- Did neither change it? Keep the base.
- Did both change it, identically? Take it once.
- Did both change it, differently? Conflict — a human decides.
This is why the merge base matters so much. Without it, Git could only see that two files differ, not which side changed what. With it, “both sides changed the same region” becomes a question Git can answer mechanically.
Why merge policy is not a detail
Section titled “Why merge policy is not a detail”Which merge method a team uses shapes things that are hard to change later.
History readability. git log main either reads as a sequence of changes or as a braid of
interleaved branches, depending entirely on how branches were integrated.
Debugging. git bisect works on any history, but it is far more useful when each commit on main
builds and passes tests. A merge strategy that puts intermediate work-in-progress commits on main
undermines it.
Auditing. A merge commit records when a branch was integrated and by whom. Squashing discards that, replacing it with a single commit whose author is whoever wrote the code, not whoever integrated it.
Code review. If main gets one commit per pull request, reviewing main’s history is reviewing
units of work. If it gets every intermediate commit, reviewing history means wading through “fix typo”.
Reverting. Undoing a squashed change is one revert. Undoing a merge commit requires telling Git which parent to keep. Undoing a rebased series means reverting several commits.
None of these has a universally right answer, which is why this cluster covers each method on its own terms rather than recommending one.
What this cluster covers
Section titled “What this cluster covers”- Lesson 1: 01. Git Merge ExplainedMerging combines two histories by finding their merge base and reconciling both sets of changes. A complete guide to how git merge works.
- Lesson 2: 02. Fast-Forward vs Three-Way MergeWhether Git can fast-forward depends entirely on ancestry. Learn the difference, the flags that control it, and which to prefer when.
- Lesson 3: 03. Merge CommitsA merge commit is the only commit with more than one parent. Learn what that buys you, what it costs, and how reverting one differs.
- Lesson 4: 04. Squash MergingSquash merging collapses a branch into a single commit. Learn how git merge --squash differs from GitHub's squash button, and the trade-offs.
- Lesson 5: 05. Rebase and MergeRebase-and-merge replays each commit onto the target branch. Learn what it does to commit IDs, authorship and history, and when to choose it.
- Lesson 6: 06. Resolving Merge ConflictsConflicts happen when both sides change the same region. Learn to read conflict markers, resolve them safely, and verify the result.
- Lesson 7: 07. Advanced Merge StrategiesBeyond the default: merge strategies versus strategy options, rename detection, octopus and ours merges, and custom merge drivers.
Lesson 1 is the cornerstone: the merge base, fast-forward versus three-way, what git merge actually
does, and how to inspect and abort.
Lesson 2 covers fast-forward versus three-way merges specifically, because the distinction is
entirely about ancestry and is the source of a lot of confusion about --no-ff and --ff-only.
Lesson 3 covers merge commits: the only commits with more than one parent, and what that buys and costs.
Lessons 4 and 5 cover the two integration methods that are not really merges — squashing and rebase-and-merge — including where the platform button differs from the Git command.
Lesson 6 is the practical centrepiece: resolving conflicts, worked through in a repository you build yourself specifically to break.
Lesson 7 covers Git’s merge strategies and their options, rename detection, and custom merge drivers.
The four ways work reaches a branch
Section titled “The four ways work reaches a branch”Teams talk about “merging” as one thing. In practice there are four distinct operations, and they produce different histories from identical code.
| Operation | Commits added to the target | New commit IDs? | Merge commit? |
|---|---|---|---|
| Fast-forward | The branch’s commits, unchanged | No | No |
| Three-way merge | The branch’s commits plus a merge commit | No (except the merge commit) | Yes |
| Squash | One new commit containing everything | Yes, one | No |
| Rebase then merge | One new commit per original commit | Yes, all of them | No |
The first two are git merge. The third is git merge --squash followed by a commit, or a platform
button. The fourth is git rebase followed by a fast-forward, or a platform button.
Only the first two preserve the original commit objects. The other two create new ones — which is why a
branch integrated by squash or rebase will still show as “not merged” to git branch -d, and why those
methods are unsafe on branches other people have based work on.
Reading a merge afterwards
Section titled “Reading a merge afterwards”Three commands answer most questions about how something reached a branch.
Did this branch get merged?
git branch --merged mainLists branches whose tip is reachable from main. Note that a squashed or rebased branch will not
appear here even though its changes did land — the commits on main are different objects.
What did this merge bring in?
git log --oneline main..featureWhich commits are merge commits?
git log --oneline --merges mainOr the inverse, --no-merges, to read main as a flat list of changes while ignoring integration points.
Prerequisites
Section titled “Prerequisites”From Pillar 1:
- Git Objects Explained — commits as immutable objects with parent links. A merge commit is just a commit with two parent lines.
- Understanding the Git Index — during a conflict the index holds three versions of each conflicted file, which is exactly the three-way comparison made concrete.
- Understanding the Working Tree — conflict markers live in the working tree,
and
git statusreports the conflicted state.
From this pillar:
- Git Branches Explained for divergence and
git merge-base.
Merging or rebasing?
Section titled “Merging or rebasing?”Both integrate work; they differ in what they leave behind. Merging preserves both histories and records the integration as a commit with two parents. Rebasing rewrites one side onto the other, producing a linear history and new commit IDs.
The short rule, expanded properly in Rebase vs Merge:
Merge when the branch is shared or when you want the integration recorded. Rebase while the branch is still private and you want a linear result.
This cluster covers merging on its own terms. Cluster 3 covers rebasing, and the comparison lives there because rebasing is the operation that needs the safety context.
A note on terminology
Section titled “A note on terminology”Two words in this cluster are used inconsistently across the industry, and this cluster is deliberate about them.
“Merge” as mechanism versus policy. git merge is a command. “Our merge strategy” usually means the
team’s integration policy, which may not involve git merge at all — GitHub’s squash button does not run
it. This cluster says merge for the operation and integration method for the policy.
“Ours” and “theirs”. These labels are relative to the operation in progress, and they invert during a rebase. Getting them backwards is one of the easiest ways to discard work silently. Resolving Merge Conflicts is precise about this.
Start with the mechanics. Once the merge base and the three-way comparison are clear, the policy questions become much easier to reason about.