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.

Recognize the failure

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.

Why this happens

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.

What you may see: git status reports both modified, and the file contains conflict markers separating the current branch from the incoming change.

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.

What you may see: git status may report modify/delete, rename/delete, or add/add conflicts instead of a simple content conflict.

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.

What you may see: The conflict looks larger than a few lines, or both sides contain logically complete but incompatible implementations of the same responsibility.

Diagnose it in this order

  1. 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. 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. 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. 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.

Choose the fix that matches the evidence

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

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.

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.

Weak approach vs safer approach

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.

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.

Continue from troubleshooting to understanding

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.

Next step

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. Practice creating a small conflict, inspect it with status and the current patch, resolve it once, then repeat and abort instead.