Technology Git merge conflict: diagnosis and safe fixes

Learn with diagrams, code, systems and practical examples.

</>
Git troubleshooting · Reviewed 2026-08-16

Git merge conflict: diagnose first, then fix

Resolve Git merge conflicts by reading repository state, reconstructing both branches’ intent, testing the combined result, and knowing when to abort safely.

01 · Recognize

Recognize the failure before changing state

Auto-merging <file>
CONFLICT (content): Merge conflict in <file>
Automatic merge failed; fix conflicts and then commit the result.

Git found changes on the current branch and the branch being merged that cannot be combined automatically. The repository is now in a merge-in-progress state, and Git is waiting for you to decide what the final integrated content should be.

The important mental model

A merge conflict is not “Git asking which branch wins.” It is Git showing you where textual or structural evidence is insufficient to infer the intended combined behavior. Your job is to understand both changes, construct the correct integrated result, verify it, and only then complete the merge.

What can produce this state

Why this happens

Cause 1

Both branches changed overlapping code

The current branch and the incoming branch modified the same lines or nearby structure in incompatible ways, so Git cannot produce one unambiguous file automatically.

Signal to look for: git status reports both modified, and the file contains conflict markers separating the current branch from the incoming change.

Cause 2

One branch deleted or renamed something the other still changes

A file or block of code may have been removed, moved, or renamed on one side while the other side continued editing the old location.

Signal to look for: git status may report modify/delete, rename/delete, or add/add conflicts instead of a simple content conflict.

Cause 3

The branches implemented the same requirement differently

Two developers may have solved the same problem using different APIs, data shapes, or abstractions. Even if both versions work alone, combining them mechanically can duplicate behavior or violate a newer design.

Signal to look for: The conflict looks larger than a few lines, or both sides contain logically complete but incompatible implementations of the same responsibility.

02 · Inspect

Diagnose it in this order

Do not jump straight to a recovery command. Each step should narrow what state the system is actually in.

  1. 01

    Confirm the receiving branch and merge state

    Run git status before editing files.

    git status

    Why this step matters: A merge updates the branch you currently have checked out. Status confirms the merge is actually in progress, shows the conflicted paths, and helps catch a merge performed in the wrong direction.

  2. 02

    Reconstruct the branch relationship

    Inspect the graph and the commits near both branch tips.

    git log --graph --oneline --decorate --all -20

    Why this step matters: You need to know what changed independently and why before deciding how those histories should meet.

  3. 03

    Inspect the conflict and the staged merge inputs

    Use the working-tree conflict plus Git’s diff views to understand what each side contributed.

    git diff
    git diff --ours -- <file>
    git diff --theirs -- <file>

    Why this step matters: Conflict markers show only the immediate overlap. The surrounding diff and history reveal whether one side renamed an API, changed an invariant, or already superseded the other implementation.

  4. 04

    Verify the integrated behavior before committing

    After editing and staging the intended result, run focused tests, type checks, builds, or manual checks for the affected behavior.

    Why this step matters: A clean index only tells Git the conflict is resolved. It does not prove the application still satisfies both branches’ intended requirements.

03 · Choose

Choose the fix that matches the evidence

A recovery action is safe only when its assumptions match what the diagnostics showed.

Fix path 1

Resolve deliberately and complete the merge

Use this when: Use this when the merge direction is correct and you can explain how both branches’ intended behavior should coexist.

  1. Read the surrounding code and relevant commits before deleting conflict markers.
  2. Edit each conflicted file into the intended integrated state rather than choosing a side wholesale.
  3. Run focused verification for the behavior touched by both branches.
  4. Stage the reviewed files and complete the merge commit.
git add <resolved-files>
git status
git commit
Fix path 2

Abort and return to the pre-merge state

Use this when: Use this when you merged the wrong branch, the conflict set reveals a flawed integration plan, or you cannot yet determine the correct combined behavior.

  1. Stop making speculative conflict edits.
  2. Inspect git status so you know the repository is in a merge state.
  3. Abort the merge, then revisit branch direction, prerequisite changes, or the intended integration strategy.
git merge --abort

Caution: If you had unrelated uncommitted changes before the merge, inspect carefully. Keeping the working tree clean before risky integration work makes abort and recovery more predictable.

Fix path 3

Resolve a delete/modify conflict by deciding whether the file should exist

Use this when: Use this when one branch deleted a file while the other branch changed it.

  1. Find why the file was deleted on one side and why it was modified on the other.
  2. If deletion is correct, remove the file and stage that decision.
  3. If the functionality is still required, adapt the change to the replacement location or restore an intentionally updated version.
  4. Verify callers, imports, tests, and generated artifacts before completing the merge.

Caution: Do not restore a deleted file merely because it makes the conflict disappear; the deletion may represent an architectural change that the older modification must be adapted to.

04 · Verify

Prove the recovery worked

A command succeeding is not the same as the system being correct. Compare the tempting shortcut with the evidence-led path, then verify the resulting state.

Tempting but risky
git checkout --theirs src/app.ts
git add src/app.ts
git commit

This can make Git happy while throwing away the current branch’s required behavior. “Theirs” means the incoming side of this merge, not “the correct implementation.” A conflict is evidence that the final file may need parts of both sides—or a third version that reflects a newer design.

Evidence-led
git status
git log --graph --oneline --decorate --all -12
git diff
# integrate the intended behavior from both branches
npm test -- --runInBand relevant-test
git add src/app.ts
git status
git commit

This sequence confirms merge direction, reconstructs the histories, examines the actual overlap, verifies the integrated behavior, and only then records the merge result.

Verification checklist
  • Inspect the current state again instead of assuming the recovery command finished cleanly.
  • Run the narrowest relevant tests or checks that prove the intended behavior still works.
  • Review the resulting history or state transition for anything the recovery changed unexpectedly.
  • Only resume normal work when the evidence matches the intended outcome.
Reduce repeat failures

Prevent the same class of failure

  • Keep feature branches focused and integrate shared foundational changes early so two branches are less likely to redesign the same code independently.
  • Fetch and inspect the target branch before merging; knowing the graph and recent commits makes surprising conflicts less likely.
  • Prefer small coherent commits with clear messages so a conflict can be mapped back to business or technical intent instead of unexplained file churn.
  • Keep the working tree clean before merges so abort and recovery are predictable.
  • Maintain focused tests around integration boundaries such as schemas, APIs, configuration, and shared components; these catch semantically wrong conflict resolutions that compile successfully.
Questions that come up in practice

Frequently asked questions

What is the difference between a merge conflict and a rebase conflict?

A merge conflict occurs while Git is combining two existing histories into one merge result. A rebase conflict occurs while Git replays commits one at a time onto a new base. The conflict markers can look similar, but the repository state and the meaning of ours/theirs differ, so use the recovery command for the operation actually in progress.

Can I just delete the conflict markers and commit?

Only if the remaining code is intentionally the correct integrated result. Removing markers is not the goal; preserving the required behavior from both histories is. Read the surrounding changes and run focused verification before committing.

What does git merge --abort do?

It stops the in-progress merge and attempts to restore the pre-merge state. It is the right choice when the merge direction or integration plan is wrong or you need more context before resolving. A clean working tree before the merge makes this recovery path safer.

Why does Git say the conflict is resolved after git add?

Staging tells Git that you have chosen the file content for the merge result. It does not validate application behavior. Tests, type checks, builds, or domain-specific verification are still necessary before the merge commit is trustworthy.

Practice the recovery

Reproduce the failure in a disposable repository.

Good troubleshooting skill comes from learning what the system state looks like before and after each recovery action. Recreate a small failure, inspect the evidence, recover it once, then repeat and deliberately choose the safe rollback path.

More Git troubleshooting