Great work!

XP to next level

BugEater

Why Conflicts Happen

Learning Objectives

By the end of this lesson you will be able to:

  • State the exact condition that causes a merge conflict
  • Predict which changes will conflict and which will not
  • Recognise the situations that produce conflicts most often in practice
  • Reduce how frequently your team hits them

The Exact Condition

A conflict occurs when, since the merge base:

both branches changed the same lines of the same file, in different ways.

Every word in that sentence carries weight. Same file is not enough. Same file and overlapping lines and differing content is the condition.

There is a small set of related cases Git also cannot decide alone:

  • One branch modified a file the other branch deleted
  • Both branches added a new file at the same path, with different content
  • One branch renamed a file the other branch modified heavily

They all reduce to the same principle: two answers, no rule for choosing.

What Does Not Conflict

This is the part worth internalising, because it dissolves most of the fear:

Situation Result
Different files changed Clean merge
Same file, different functions or sections Clean merge
Same file, one branch added at the top, other at the bottom Clean merge
Both branches made the identical change Clean merge
Same lines, different content Conflict

Git merges by content, not by file. Two people can work in one 2,000-line file all week and never conflict, as long as they stay in different neighbourhoods.

A Concrete Example

The merge base has this in config/test-env.yaml:

timeout: 30
retries: 2
base_url: https://staging.example.com

On main, someone raised the timeout:

timeout: 60
retries: 2
base_url: https://staging.example.com

On dev, someone else raised it differently and also changed retries:

timeout: 45
retries: 5
base_url: https://staging.example.com

Merging dev into main produces:

  • timeout — both branches changed the same line to different values → conflict. Git has no basis for preferring 60 over 45.
  • retries — only dev changed it → clean. Git takes 5.
  • base_url — neither changed it → clean. It stays as it was.

One conflicted line out of three. That is the typical shape of a real conflict: small, specific, and about a decision a human has to make.

Where Conflicts Actually Come From

In practice, a handful of patterns account for most of them:

Long-lived branches. A branch open for three weeks has three weeks of drift. This is the biggest single cause, and Lesson 2.3's refresh habit is the fix.

Shared configuration files. test-env.yaml, package.json, docker-compose.yml, CI pipeline definitions. Everyone touches them and they are small, so edits land close together.

Generated and lock files. package-lock.json, yarn.lock, compiled output committed to the repository. These regenerate completely on every change and conflict constantly. Most teams handle them by regenerating rather than merging.

Auto-formatters run at different times. One branch reformats a file, another edits it normally, and suddenly every line differs. This is why teams standardise on one formatter and one configuration.

Two people fixing the same bug. Rare, and mildly embarrassing, but it happens on busy teams and produces a genuinely tricky conflict.

Reducing Them

You cannot eliminate conflicts, and a team with zero conflicts is usually a team where nobody is working in parallel. But you can keep them small:

  • Merge main into your branch often — daily if main is busy.
  • Keep branches short-lived. A branch that lives two days conflicts far less than one that lives two weeks.
  • Commit in small, focused units. A conflict inside a 12-line commit is readable; one inside a 600-line commit is an ordeal.
  • Say what you're touching. "I'm changing the timeout in test-env.yaml this afternoon" costs one message and prevents the whole thing.

Pro Tip: Before merging a branch that has been open a while, run git diff main...your-branch --stat. If any file appears there that you know is also under active change on main, you have just predicted your conflict — and you can deal with it deliberately instead of by surprise.

Key Takeaways

  • A conflict needs the same lines of the same file changed differently on both sides
  • Different files, different sections, or identical changes all merge cleanly
  • Modify/delete, add/add and rename cases conflict for the same underlying reason
  • Long-lived branches, shared configs, lock files and formatter runs cause most real conflicts
  • Frequent refreshes and short-lived branches are the effective prevention
  • git diff main...branch --stat predicts where a conflict is likely before you merge

Quiz

What exactly causes a merge conflict?

Branch A changed timeout on line 1; branch B changed retries on line 2 of the same file. What happens?

Which of these is the single biggest practical cause of conflicts?

Both branches added a new file at the same path, with different content. What does Git do?