By admin , 28 April 2026

Introduction

The merge base of two commits is their best common ancestor: the foundation Git uses for three-way merges. Choosing the right base is what makes "automatic" merges actually work.

Finding it

git merge-base A B
git merge-base --all A B           # all best common ancestors
git merge-base --octopus A B C
git merge-base --is-ancestor X Y   # exit 0 if X is ancestor of Y
git merge-base --fork-point main feature

Definition

A common ancestor C of A and B is a "best" common ancestor if no other common ancestor of A and B is a descendant of C. Most pairs have a single best common ancestor. When the graph contains crisscross merges, several can exist; that is what --all reports.

How three-way merge uses it

Given commits A and B with merge base M, Git for each file:

  1. Reads the file at M, A, and B.
  2. If only one side changed, take that side.
  3. If both sides changed identically, take either.
  4. If both sides changed differently, run a three-way text merge or emit conflict markers.

Recursive and ort strategies

When several merge bases exist, the recursive strategy merges them first, producing a virtual base, and uses that for the final three-way merge. The ort strategy (default since 2.33) does the same with a faster, more memory-efficient implementation.

git merge -s ort feature
git merge -s recursive feature
git merge -s resolve feature       # only one merge base, no recursion

Fork point

For rebase, Git often needs to know where a topic branch left a base branch. --fork-point consults the reflog of the base to find the most recent point at which the topic and base shared history:

git rebase --fork-point main feature
git merge-base --fork-point main feature

Worked example

A---B---C   main
     \
      D---E   feature

git merge-base main feature   # B

A merge of main into feature three-way merges using B as the base.

Inspecting why a merge conflicts

git merge-base HEAD feature
git diff <base> HEAD -- file
git diff <base> feature -- file

This pair of diffs is exactly what Git's merge sees.

Common mistakes

Assuming there is always exactly one merge base; crisscross histories produce several. Treating --fork-point as a substitute for --onto; they solve different problems. Picking --strategy=ours when you meant --strategy-option=ours; the first discards their changes entirely. Finally, recomputing the merge base by hand from git log output and getting it wrong; use git merge-base rather than eyeballing.