Three-Way Merge

Updated

October 30, 2026

Three-Way Merge Explained

After this page you can draw the three inputs Git uses when two branches diverged.

The three trees

Call them:

Name What
Base Merge base: latest common ancestor of both tips
Ours The branch you have checked out (HEAD)
Theirs The branch you named in git merge

Git diffs base→ours and base→theirs, then applies both diffs to the base. That is a three-way merge. A two-way merge (ours vs theirs only) cannot tell “we both added the same line” from “they added a line we never had.”

          C  base     (merge-base main feat)
         / \
        /   \
      G     E         ours = main, theirs = feat
        \   /
         \ /
          M  result   two-parent merge commit

See the base

cd ~/desk/desk-api
git merge-base main feat/ping-json
git log --oneline --graph main feat/ping-json

merge-base prints one hash. git log --graph should make that node obvious.

Stages in the index during a conflict

When both sides changed the same hunk, Git records three stages for that path in the index:

Stage Content
1 base
2 ours
3 theirs
git ls-files -u

git checkout --ours path / --theirs path copies stage 2 or 3 into the working tree. You still git add after you edit. The next page is the full conflict loop.

Why this matters for a forge

A pull request / merge request is this same three-way merge, run on the server when you click Merge. The conflict you see in the UI is stages 2 and 3 plus markers. Learning it locally means the UI is not a new theory.

zdiff3 markers

With merge.conflictstyle zdiff3 (chapter 2) a conflicted file shows the common ancestor as well as ours and theirs. That extra block is the base. Read it before you delete markers.