EMZETT.
Login

Merge Conflicts

In short: Occurs in Git when two changes have modified the same line of code differently and Git can’t automatically decide which version applies.

In more detail: Typically happens when merging two branches. Git marks the affected spots in the code with conflict markers (<<<<<<<, =======, >>>>>>>), and a human has to manually decide which change to keep, before the merge can be completed.

In Depth

Reading conflict markers

<<<<<<< HEAD
const discount = 0.10;
=======
const discount = 0.15;
>>>>>>> feature/new-discount

The section between <<<<<<< HEAD and ======= shows the version in the current branch (usually the one being merged into), the section between ======= and >>>>>>> <branch-name> the incoming version from the other branch. Git can automatically merge changes as long as they affect different lines — only when the same line (or directly adjacent lines) has been changed on both sides can Git not decide for itself which version is “correct”, and marks the spot as a conflict.

Resolving a conflict

The developer then has to decide manually: keep one side completely, sensibly combine both changes, or write something entirely new that takes both original intentions into account. Afterwards, the conflict markers themselves have to be removed (they’re plain text that Git doesn’t delete automatically) and the state marked as resolved (git add on the affected file, then git commit to complete the merge). Modern code editors (VS Code, IntelliJ) often offer a graphical interface for this, with buttons like “Accept Current”, “Accept Incoming” or “Accept Both”, which makes manually editing the markers unnecessary.

Causes and prevention

Conflicts pile up especially with:

  • Long-lived branches: that have drifted far from the main branch, so many independent changes collide at the final merge.
  • Parallel work on the same code spots: several people editing the same function/file at the same time, without knowing about each other.
  • Automatically formatted code: when a code formatter (Prettier, Black) reformats large parts of a file, practically the entire file appears “changed”, which makes conflicts with other parallel changes more likely.

Frequent, small-step merging/rebasing (regularly syncing your own branch with the current main branch, instead of only after weeks) keeps diffs small and thereby reduces both the likelihood and the complexity of conflicts — one large, rare merge after weeks of isolated work is almost guaranteed to have more conflicts than many small, regular ones.

See also: Git, GitHub