Skip to content
DevOps devops git 5 min read

Resolving Merge Conflicts

A merge conflict happens when Git tries to combine two sets of changes but cannot decide which version to keep. This is not a bug or a sign you did something wrong. It simply means two people (or two branches) edited the same part of the same file in different ways, and Git needs a human to choose the right answer. Learning to read and resolve conflicts calmly is one of the most useful Git skills you can have, because every team that ships code will hit them eventually.

Why conflicts happen

Git is very good at merging changes automatically. If you change the top of a file and your teammate changes the bottom, Git stitches both edits together without asking. A conflict only appears when the edits overlap.

The most common triggers are:

  • Two branches change the same line of the same file in different ways.
  • One branch deletes a file while another branch edits the same file.
  • A line was added in the same spot by both branches.

Git stops the merge, marks the file as “conflicted”, and waits for you to fix it. Until you do, the merge is paused, not finished.

Conflicts are normal. On an active team you will resolve them weekly. The goal is not to avoid them entirely but to resolve them quickly and correctly.

Spotting a conflict

You usually discover a conflict right after running a merge or a pull. Imagine you are merging a branch called feature-login into main.

git checkout main
git merge feature-login

Output:

Auto-merging app/config.py
CONFLICT (content): Merge conflict in app/config.py
Automatic merge failed; fix conflicts and then commit the result.

To see exactly which files are stuck, run:

git status

Output:

On branch main
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to cancel the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   app/config.py

The phrase both modified is the key signal: both branches touched this file.

Reading the conflict markers

Open the conflicted file in any editor. Git inserts special marker lines so you can see both versions side by side.

database_url = "localhost:5432/devdb"
<<<<<<< HEAD
timeout_seconds = 30
log_level = "INFO"
=======
timeout_seconds = 60
log_level = "DEBUG"
>>>>>>> feature-login
max_connections = 20

Here is what each marker means:

MarkerMeaning
<<<<<<< HEADStart of your version (the branch you are on, here main).
=======The divider between the two versions.
>>>>>>> feature-loginEnd of the incoming version (the branch being merged in).

Everything between <<<<<<< HEAD and ======= is what is already on your current branch. Everything between ======= and >>>>>>> is what the other branch wants. The lines outside the markers (database_url and max_connections) merged cleanly and need no attention.

Resolving the conflict

Your job is to edit the file so it contains the final, correct code, then delete all three marker lines. There is no single “right” choice. You might keep your version, keep theirs, or blend both.

Say the correct result is a 60-second timeout but INFO logging. You edit the file to look like this:

database_url = "localhost:5432/devdb"
timeout_seconds = 60
log_level = "INFO"
max_connections = 20

Notice every <<<<<<<, =======, and >>>>>>> line is gone. If you forget one, your program will likely fail to run because those markers are not valid code.

Always search the whole file for <<<<<<< before committing. A single leftover marker can break a build and slip into production. Run grep -rn '<<<<<<<' . to scan an entire project at once.

The resolve, add, commit flow

Once the file looks right, you tell Git the conflict is settled. The pattern is always the same: edit, then add, then commit.

git add app/config.py
git status

Output:

On branch main
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Changes to be committed:
        modified:   app/config.py

Running git add on a previously conflicted file is how you mark it resolved. When every file is added, finish the merge:

git commit

Git opens an editor with a pre-filled merge message like Merge branch 'feature-login'. Save and close it, and the merge is complete.

Output:

[main 9f3c1a7] Merge branch 'feature-login'

When to bail out

If a merge looks too tangled and you would rather start over, you can cancel it completely. This returns your branch to exactly how it was before the merge began.

git merge --abort

This is safe and discards nothing from your committed history. Use it any time you feel lost partway through a resolution.

Tools that make it easier

You do not have to resolve conflicts by hand in a plain text editor. Several tools show the two versions in a clear three-way view.

ToolWhen to use it
VS CodeBuilt-in conflict view with “Accept Current / Incoming / Both” buttons. Best for everyday work.
git mergetoolLaunches a configured diff tool (like Meld) from the terminal. Good on servers without an editor GUI.
git checkout --ours / --theirsQuickly keep one whole side of a file when you know it is correct.

On Ubuntu you can install Meld, a friendly visual merge tool, with:

sudo apt update
sudo apt install meld
git config --global merge.tool meld

Then run git mergetool during a conflict to open each file visually.

Best practices

  • Pull and merge often. Small, frequent merges produce tiny conflicts instead of huge ones.
  • Read both sides fully before editing. Understand the intent, not just the lines.
  • Delete every conflict marker, then grep to confirm none remain.
  • Test or run your code after resolving, before you commit. Resolving wrong is easy to do silently.
  • Use a visual merge tool for anything more than a few lines.
  • When unsure, ask the teammate who wrote the other side which version is correct.
  • Remember git merge --abort exists. You can always reset and try again calmly.
Last updated June 15, 2026
Was this helpful?