Merge Conflicts
What Will We Learn?
In this article, we’ll understand what a merge conflict is, why it occurs, what Git does internally when it runs into one, and what practices you can follow to keep conflicts rare and easy to resolve.
What is Merge Conflict?
A merge conflict happens when Git tries to combine changes from two branches, but finds that the same part of a file has been changed differently in both branches. Git doesn’t know which version you actually want to keep, so instead of guessing, it stops the merge and asks you to decide manually.
Let’s say you have a main branch and a feat branch, both starting from a common commit B. If main moves forward with commit C, and feat moves forward with commit D, and both C and D modify the same line in the same file, Git cannot automatically figure out which change should “win.” That’s a merge conflict.
C (main)
/
A - B
\
D (feat)Here, both C and D diverge from B. If they touch different files or different lines, Git merges them automatically. If they touch the same line, Git needs your help.
Why Merge Conflict Occurs?
Merge conflicts don’t happen randomly — they occur for specific, identifiable reasons. Let’s go through them one by one.
Same line, different changes
This is the most common cause. If you change line 10 of app.js in your branch, and someone else also changes line 10 of app.js in their branch, Git has two different versions of the same line and can’t merge them silently.
File deleted in one branch, modified in another
If your branch deletes a file entirely, but the other branch modifies the same file, Git isn’t sure whether the file should exist or not after the merge. It flags this as a conflict rather than silently deleting something that was actively being worked on.
Branches diverging for a long time
The longer a branch lives without syncing with main, the more its content drifts apart from main. This increases the surface area for overlapping changes, and by the time you merge, there’s a much higher chance both branches touched the same code.
File renames or moves
If one branch renames utils.js to helpers.js, and another branch edits the original utils.js, Git has to figure out that these are “the same file” under the hood. This detection isn’t always perfect, and it can result in a conflict.
Manual merges of unrelated histories
If you merge two branches that don’t share a common ancestor (using --allow-unrelated-histories), Git has very little context to work with, which makes conflicts far more likely.
What Happens After Merge Conflict?
When Git detects a conflict, it does not fail the merge outright — it pauses the merge process midway and leaves your working directory in a special “merging” state. Here’s what happens step by step:
1. Git marks the conflicting file(s)
Any file with a conflict is left in your working directory with special conflict markers inserted directly into the content:
<<<<<<< HEAD
This is your current branch's version of the line.
=======
This is the incoming branch's version of the line.
>>>>>>> feat- Everything between
<<<<<<< HEADand=======is what your current branch (HEAD) has. - Everything between
=======and>>>>>>> featis what the branch you’re merging in (feat) has.
2. Git reports the status
If you run git status at this point, Git will list the conflicting files under a section like “Unmerged paths,” so you know exactly which files need your attention before the merge can be completed.
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: app.js3. You resolve the conflict manually
You open each conflicting file, look at the changes on both sides, and decide what the final content should be. This might mean:
- Keeping your version entirely.
- Keeping the incoming version entirely.
- Combining both versions into something new.
Once you’ve decided, remove the conflict markers (<<<<<<<, =======, >>>>>>>) — leaving them in place will break your code even though the file no longer looks like it’s in conflict.
4. Stage the resolved file
After editing, tell Git the conflict is resolved by staging the file:
git add app.js5. Complete the merge
Once all conflicting files are staged, finish the merge by committing:
git commitGit will usually pre-fill a commit message like Merge branch 'feat' into main — you can keep it as is or customize it.
6. Or, abort the merge entirely
If you realize halfway through that you’d rather not merge right now, you can cancel everything and return to the state before the merge started:
git merge --abortThis restores your working directory exactly as it was, with no trace of the attempted merge.
Best Practices for Avoiding Merge Conflicts
Pull frequently — Regularly pull the latest changes from
maininto your working branch. The smaller the gap between your branch andmain, the less likely you are to collide with someone else’s changes.Keep branches short-lived — Merge feature branches back as soon as they’re ready instead of letting them sit for weeks. Long-lived branches are the single biggest cause of painful conflicts.
Communicate with your team — If multiple people need to work on the same file or module, a quick heads-up can prevent two people from editing the same lines at the same time.
Commit small, focused changes — Small, well-scoped commits are easier to merge, and if a conflict does happen, it’s much easier to understand what changed and why.
Use
.gitattributesfor generated or binary files — For files like lockfiles or build artifacts, configure a merge strategy (e.g.,merge=ours) so Git doesn’t try to line-by-line merge content that isn’t meant to be merged manually.Review before merging — Use
git diffor open a pull request to review incoming changes before merging, so conflicts (if any) don’t come as a surprise.Rebase feature branches regularly — Running
git rebase mainon your feature branch periodically keeps your branch up to date and surfaces conflicts early, in smaller, more manageable chunks, rather than all at once at the end.
Following these practices won’t eliminate merge conflicts entirely — they’re a natural part of collaborative development — but they’ll make them rare, and when they do happen, much easier to resolve.