TRLet’s talk
← Argo Ajans

Corporate Software

How to resolve a git merge conflict: a step-by-step guide

Mehmet Said Göksu ·

How to resolve a git merge conflict: a step-by-step guide

Short answer

A git merge conflict happens when two branches change the same line in different ways. To fix it, run git status to find the conflicted files, choose the correct lines from between the <<<<<<</=======/>>>>>>> markers, delete the markers, mark the file with git add, and finish with git commit.

These steps work the same way on every editor and every operating system; the only thing that changes is which tool displays the merge conflict.

What is a merge conflict, and why does it happen?

When a team works on parallel branches of the same project, Git automatically merges most changes on its own. But if two branches change the same line of the same file in different ways, or if one branch deletes a file that another branch has kept editing, Git cannot decide which change is correct. The merge stops, and a merge conflict appears — the whole point of a merge conflict is to stop an unsafe guess.

This is not a bug — it is a deliberate safety mechanism. According to Git’s official book, Git is smart about detecting when a merge result is unambiguous, but when there is genuine ambiguity, it does not try to be clever about guessing; it leaves the decision to a person. In other words, every merge conflict is Git saying “I would rather ask you than guess wrong here.”

The most common scenarios that trigger a merge conflict are:

  • Two developers editing the same function or the same configuration file at the same time
  • A feature branch that stayed apart from the main branch for a long time being merged after main has changed substantially
  • A file being deleted on one branch while another branch keeps editing it
  • Automatic formatting tools reformatting the same file differently on different branches

Finding conflicted files with git status

When a git merge or git pull command results in a merge conflict, you will see a message like this in the terminal:

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

Rather than tracking every merge-conflicted file through scattered terminal messages, running git status gives a reliable, complete list:

$ git status
On branch feature/checkout-form
You have unmerged paths.
  (fix conflicts and run "git commit")

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

The both modified label means that file has a merge conflict and both sides changed it. A large merge can produce a merge conflict in dozens of files at once, so seeing the full git status list before you start fixing anything is the first step to not missing one.

Reading the conflict markers

Git inserts its own markers directly into every file with a merge conflict. For example, if two branches changed the same line differently, the file looks like this:

<<<<<<< HEAD
const VAT_RATE = 0.20;
=======
const VAT_RATE = 0.18;
>>>>>>> feature/tax-update

Read this block in three parts:

  • The section between <<<<<<< HEAD and ======= is the version on the branch you currently have checked out (usually your own latest change).
  • The section between ======= and >>>>>>> branch-name is the version from the branch you are merging in.
  • The name after >>>>>>> tells you which branch the incoming change came from — useful for knowing who to talk to.

The fix is to remove all three markers (<<<<<<<, =======, >>>>>>>) entirely and leave only the correct lines. Sometimes the right answer is to keep both sides, sometimes to combine them, and sometimes to discard both and write a third value — Git does not suggest an answer; the person reading the content decides.

How to resolve a git merge conflict, step by step

Resolving a merge conflict is the same five steps regardless of which tool you use to fix the merge conflict: find the file, read the markers, decide on the correct content, clean up the markers, and commit the result.

Resolving it from the command line

  1. Run git status to list every conflicted file.
  2. Open each conflicted file in a text editor and go through the <<<<<<</=======/>>>>>>> blocks one by one.
  3. Decide which lines should stay and delete the markers.
  4. Mark each file as resolved with git add:
git add src/app.js
git add src/config.json
  1. Once every conflicted file has been staged with git add, finish the merge:
git commit

Git usually proposes an automatic message for this commit (something like “Merge branch ‘feature/tax-update’”), which is fine to keep as-is in most cases. If the merge conflict turns out to be more complex than expected, or you realise you merged the wrong branch, git merge --abort cancels the merge and returns the branch to its clean state — but only before the merge commit has been made.

Resolving it in VS Code or another editor

A visual merge conflict tool makes resolving the merge conflict easier to follow. Editors like VS Code show clickable shortcuts such as “Accept Current Change”, “Accept Incoming Change”, and “Accept Both Changes” when you open a conflicted file; these shortcuts remove the same markers behind the scenes and leave the correct lines. For conflicts with several blocks, a visual tool lowers the risk of mistakes; for small, single-line conflicts, the command line is usually faster. Whichever tool you use, running git add before confirming that no <<<<<<< or >>>>>>> marker is left in the file is a common mistake that lets a stray marker slip into the code unnoticed.

Merge conflicts in lock files and binary files

Auto-generated lock files such as package-lock.json, yarn.lock, or composer.lock produce a merge conflict often; instead of resolving them line by line, it is usually safer to delete the lock file and re-run the package manager’s install command (npm install, yarn install, and so on), since the result then stays consistent with the dependency tree. For binary files — images, video, compiled packages — Git cannot place a line-by-line marker inside the file at all; you decide which version to keep and select it with git checkout --ours <file> or git checkout --theirs <file>, then stage it with git add.

Resolving a merge conflict inside a GitHub pull request

When a pull request shows “This branch has conflicts that must be resolved” — GitHub’s own phrasing for a merge conflict — there are two paths. If the conflict is confined to a single, non-binary file and is relatively simple, GitHub’s own web-based conflict editor can handle it: it shows the same <<<<<<</=======/>>>>>>> markers in the browser and turns your edit directly into a commit. GitHub’s official documentation walks through both methods in detail.

If the merge conflict spans multiple files, involves a large binary file (an image, a design file, a compiled package), or is structurally complex, resolving it in the browser is risky; pulling the branch locally, resolving the conflict on the command line, testing the result, and only then pushing is safer. Resolving a merge conflict purely by “keep the red, drop the green” without running the code removes the conflict, but it does not guarantee a working result — which is why complex conflicts should always be followed by a test run.

How rebase conflicts differ from merge conflicts

The same merge conflict markers and the same resolution logic apply when using git rebase, but the process unfolds differently. A merge has a single conflict moment and ends in a single commit. A rebase reapplies every commit on your branch one at a time, so if the same line changed across multiple commits, the same conflict can appear more than once, once for each affected commit. After resolving each one, git add marks it and git rebase --continue moves on to the next commit; if you want to stop the process, git rebase --abort returns the branch to its state before the rebase started.

A practical rule for teams: rebasing a shared branch that other people are also working on carries extra risk because it rewrites history; deciding when that risk is acceptable is part of the team’s version control and release process. The small-and-frequent-delivery principle from our DevOps guide applies here too: the longer a branch stays apart from main, the more merge conflicts pile up and the more complex they get at merge time.

Ways to prevent merge conflicts

Reducing every merge conflict to zero is not realistic, but reducing their frequency and size is:

  • Keep branches short-lived. The longer a feature branch stays separate from main, the more changes accumulate before it comes back, and the higher the conflict risk.
  • Pull from main frequently. Regularly bringing main’s changes into your branch with git pull or git merge main means dealing with small, frequent conflicts instead of one large accumulated diff.
  • Keep files small and focused. When too much responsibility piles up in a single file, the odds that more than one person touches it at the same time go up.
  • Communicate inside the team. Knowing that two people are working on the same file or module at the same time does not prevent a conflict, but it makes understanding who changed what much easier.
  • Fix formatting rules in one shared configuration. Different developers reformatting the same file with different formatter settings produces line-by-line conflicts even when the actual content did not change.

Common mistakes

  • Running git add without reading the markers. If <<<<<<< or >>>>>>> is still in the file, it slips silently into the code, and it can take days to notice.
  • Picking one side out of panic. Choosing “my change” or “the incoming change” without thinking resolves the conflict but can silently delete the other side’s change, which often had a reasonable purpose.
  • Skipping tests. Even when a conflict is resolved cleanly as text, you still need to run the relevant tests, or at least run the application locally, to confirm the result actually works.
  • Realising too late that git merge --abort was an option. Once the merge commit has been made, this command no longer works; the decision to back out has to happen before committing.
  • Letting long, infrequent merges become the norm. If the same problem keeps recurring, the thing that actually needs fixing is not each individual conflict but how long branches stay separated.

Checklist

When you hit a merge conflict, check these in order:

  • Did you run git status and see the complete list of conflicted files?
  • Did you read every <<<<<<</=======/>>>>>>> block in each file, one by one?
  • When deciding, did you ask “which change is correct” rather than just “which change is mine”?
  • After removing the markers, did you confirm no <<<<<<< or >>>>>>> was left in the file?
  • Did you run the relevant tests or the application itself after staging with git add?
  • Does the commit message make clear what was merged and why?

Next step

A git merge conflict is unavoidable once a team grows and branches multiply, but it is always solvable when you work through it in the right order. What usually makes a merge conflict worse is not the conflict itself, but a rushed decision made under pressure. Finding the file with git status, reading the markers line by line, and never committing before testing the result resolves most cases safely.

If you want to set up your team’s version control workflow, branching strategy, or release process from the ground up, take a look at our corporate software solutions or get in touch with us. Our group company Web Tasarım Ofisi also supports web projects with technical infrastructure and long-term maintenance, including version control practices. The command-line habits that make conflicts less frequent are covered in SSH and essential Linux commands, and the longer-term cost of skipping this discipline in what technical debt is.

Frequently asked questions

What is a git merge conflict?

A merge conflict happens when two branches change the same line of the same file in different ways, or when one branch deletes a file that the other branch has edited. Git cannot decide on its own which change is correct, so it pauses the merge and asks you to resolve it.

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

During a merge, Git tries to combine two branches and you hit a single conflict moment if they clash. During a rebase, each commit is reapplied one by one, so if the same line changed across several commits, the same conflict can appear multiple times, once per commit.

How should I read the conflict markers (<<<<<<<, =======, >>>>>>>)?

The section between <<<<<<< HEAD and ======= is the version on the branch you currently have checked out. The section between ======= and >>>>>>> is the version from the branch being merged in. Decide which lines should stay, then remove all three markers from the file.

When should I use git merge --abort?

If a conflict becomes too complex or you realise you merged the wrong branch, git merge --abort cancels the merge and returns the branch to its clean state before the merge started. It only works before the merge commit has been made.

How do I resolve a merge conflict inside a GitHub pull request?

If the conflict is simple, text-based, and confined to a single file, GitHub's web-based conflict editor can handle it. If the conflict spans multiple files, involves a binary file, or is structurally complex, resolving it locally on the command line and pushing the result is safer.

Need help with this?

Custom Software

Explore the serviceGet in touch
Good work starts with a conversation.

Let’s make
it matter.

Izmir office
Tariş Cd. (1497. Sok.) No. 5C Ofis P22
35230 Alsancak, İzmir, Türkiye
UK office
167 Sheen Lane
SW14 8NA London, United Kingdom
Kayseri office
Sahabiye Mh. Buyurkan Sok. No.29
38015 Kocasinan, Kayseri, Türkiye
Send your project brief