git merge brings the commits of one branch into another. Most merges are boring — a fast-forward or a clean three-way — and the interesting cases (conflicts, histories that diverged for weeks) have a stable, repeatable method. This note is that method.

The two shapes a merge takes #

Fast-forward: main just catches up
$ git switch main && git merge feature/toc
Updating f3e2d1c..9a8b7c
Fast-forward
 src/toc.js | 42 ++++++

  # Three-way: histories genuinely diverged
$ git merge feature/toc
Merge made by the 'ort' strategy.

If main has no commits since the branch left, git simply slides the label forward (fast-forward). If both moved, git creates a merge commit with two parents, weaving the lines. --no-ff forces a merge commit even when fast-forward is possible — a common team choice so feature boundaries stay visible in log.

The merge that goes wrong #

Conflict: git stops and tells you exactly where
$ git merge feature/toc
Auto-merging src/toc.js
CONFLICT (content): Merge conflict in src/toc.js
$ git status                       # list every conflicted file
$ git diff                         # see both sides at the conflict

The conflicted file holds markers:

Reading the markers
<<<<<<< HEAD
timeout = 60
=======
timeout = 120
>>>>>>> feature/toc

HEAD is your side; below ======= is theirs. Resolution is editing the file to the correct result — which is sometimes one side, sometimes a genuine combination — then:

Finish or flee
$ git add src/toc.js && git commit       # conclude the merge
$ git merge --abort                      # or: back out entirely

The method #

  1. git status — how many files are conflicted?
  2. One file at a time: read both sides, decide the correct content.
  3. git add the resolved file.
  4. git commit when all are resolved — or --abort to restart your thinking.

Tools help but do not think: git checkout --ours file / --theirs file take a whole side, and mergetool opens a three-pane view. The decision is always yours.

Choosing merge or rebase #

SituationChoose
Feature branch joins shared mainMerge (or rebase first, then merge)
You want linear historyRebase, then fast-forward merge
Shared/public branchMerge only — the golden rule forbids rebasing others' work
Long-lived divergenceMerge, and reconcile sooner next time

After the merge, verify with diff against the pre-merge state, and push. The Git series continues.