Skip to content

Git Merging

5 min readModern Git Workflows · 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 Explained

The word “merge” suggests combining two things. Git actually compares three.

Three inputs: the merge base and both branch tips

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.

ABCMXYmainfeatureB is the merge base. Git compares B→C and B→Y, then combines both sets of changes.

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.

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.

  1. 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.Beginner → Intermediate11 min read
  2. 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.Intermediate8 min read
  3. 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.Beginner → Intermediate8 min read
  4. 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.Beginner → Intermediate9 min read
  5. 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.Intermediate11 min read
  6. 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.Intermediate13 min read
  7. Lesson 7: 07. Advanced Merge StrategiesBeyond the default: merge strategies versus strategy options, rename detection, octopus and ours merges, and custom merge drivers.Intermediate → Advanced11 min read

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.

Teams talk about “merging” as one thing. In practice there are four distinct operations, and they produce different histories from identical code.

OperationCommits added to the targetNew commit IDs?Merge commit?
Fast-forwardThe branch’s commits, unchangedNoNo
Three-way mergeThe branch’s commits plus a merge commitNo (except the merge commit)Yes
SquashOne new commit containing everythingYes, oneNo
Rebase then mergeOne new commit per original commitYes, all of themNo

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.

Three commands answer most questions about how something reached a branch.

Did this branch get merged?

Terminal window
git branch --merged main

Lists 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?

Terminal window
git log --oneline main..feature

Which commits are merge commits?

Terminal window
git log --oneline --merges main

Or the inverse, --no-merges, to read main as a flat list of changes while ignoring integration points.

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 status reports the conflicted state.

From this pillar:

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.

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.