What is a merge conflict?
A merge conflict happens when Git cannot automatically combine changes from two branches because both branches modified the same lines in the same file. Git does not know which version to keep, so it pauses the merge and asks you to resolve it manually.
Conflicts are a normal part of collaboration. They are not errors — they are Git saying "I found two different edits to the same code and I need a human to decide what the final version should look like." Once you learn the pattern, resolving them takes seconds.
Merge conflicts are one of the biggest fears for Git beginners. The good news: they follow a simple, predictable pattern. After resolving a few, they stop being scary and become routine.
How conflicts happen
Conflicts occur when two branches diverge — they both have commits that the other does not — and those commits touch the same lines. Here is a typical scenario:
- You and a teammate both start from the same commit on
main. - Your teammate fixes accessibility in the
Headercomponent and pushes tomain. - Meanwhile, on your
feature/redesignbranch, you restyle the sameHeadercomponent. - When you try to merge
feature/redesignintomain, Git sees that both branches modified the same lines and raises a conflict.
Here is what the commit graph looks like — two branches that have diverged from a common ancestor:
When you run git merge, Git attempts to combine the two branches automatically. If it cannot resolve every overlap, it stops and reports the conflict:
Notice that Git tells you exactly which files have conflicts. The merge is paused, not failed — your working tree contains the conflict markers, and Git is waiting for you to fix them.
What does NOT cause conflicts
It is important to understand that not all merges produce conflicts. Git can automatically resolve most situations:
- Two branches editing different files — no conflict. Git combines both sets of changes.
- Two branches editing different parts of the same file — no conflict. Git merges both hunks independently.
- One branch adds a file, the other does not touch it — no conflict.
Conflicts only arise when both branches modify the same lines (or one deletes a file the other modified).
Reading conflict markers
When Git encounters a conflict, it inserts special markers directly into the file. Open the conflicting file and you will see something like this:
import { useState } from 'react';
export default function Header() {
<<<<<<< HEAD
return (
<header className="header" role="banner">
<nav aria-label="Main navigation">
<a href="/" className="logo">My App</a>
</nav>
</header>
);
=======
const [menuOpen, setMenuOpen] = useState(false);
return (
<header className="header-redesign">
<div className="logo-wrapper">
<a href="/">My App</a>
</div>
<button onClick={() => setMenuOpen(!menuOpen)}>
Menu
</button>
</header>
);
>>>>>>> feature/redesign
}There are three markers to look for:
<<<<<<< HEAD— Marks the beginning of your version (the branch you are currently on).=======— The divider between the two versions.>>>>>>> feature/redesign— Marks the end of their version (the branch being merged in).
Here is how the two sides look in a diff view:
Code outside the conflict markers was merged automatically and is fine. You only need to deal with the sections between<<<<<<<<and>>>>>>>.
Multiple conflicts in one file
A single file can have more than one conflict zone. Each zone has its own set of <<<<<<<< / ======= / >>>>>>> markers. You must resolve every zone before the file is considered clean.
Multiple conflicting files
A merge can also produce conflicts in more than one file. Use git status to see the full list:
Files under "Unmerged paths" need to be resolved. Files under "Changes to be committed" were merged automatically and are ready.
Resolving conflicts step by step
Resolving a conflict always follows the same five-step pattern. Regardless of the complexity, the process is identical:
<<<<<<< HEAD
// Everything between <<<<<<< and =======
// is YOUR version (the branch you are on)
=======
// Everything between ======= and >>>>>>>
// is THEIR version (the branch you are merging in)
>>>>>>> feature/redesignimport { useState } from 'react';
export default function Header() {
const [menuOpen, setMenuOpen] = useState(false);
return (
<header className="header" role="banner">
<nav aria-label="Main navigation">
<a href="/" className="logo">My App</a>
</nav>
<button
onClick={() => setMenuOpen(!menuOpen)}
aria-expanded={menuOpen}
>
Menu
</button>
</header>
);
}After the merge commit, your graph shows the two branches joined together:
Aborting a merge
If you are in the middle of resolving conflicts and decide you are not ready, you can cancel the entire merge and go back to the state before it started:
Hover over each part to see what it does
This is completely safe — all conflict markers and partial resolutions are discarded, and your branch is restored to its pre-merge state. The other branch is not affected.
Resolving conflicts in Komitly
Resolving conflicts in a text editor works, but it requires you to mentally parse the markers and piece together the right version. Komitly provides a dedicated visual 3-way merge editor that makes the process dramatically easier.
The 3-way merge editor
When Komitly detects conflicting files, it opens a three-panel layout:
- Left panel — Yours (HEAD): The version on your current branch.
- Right panel — Theirs (incoming): The version from the branch being merged.
- Bottom panel — Result: The merged output. This is what will be saved to the file.
For each conflict zone, you have one-click resolution buttons:
- Accept Yours — Keep your version and discard theirs.
- Accept Theirs — Keep their version and discard yours.
- Accept Both — Include both versions one after the other.
You can also edit the result panel directly for cases where you need to write a custom resolution that combines parts of both versions (like in our Header example).
Here is what the resolved version looks like — combining the accessibility attributes from one branch with the menu button from the other:
Conflict prediction
One of Komitly's most powerful features is conflict prediction. Before you even start a merge or rebase, Komitly analyzes both branches and tells you which files will conflict. This lets you prepare ahead of time or choose a different strategy entirely.
The merge preview dialog shows a list of files that will be affected, with conflict warnings highlighted in red. You can review the potential conflicts, decide whether to proceed, or abort before anything happens.
Conflicts during interactive rebase
Conflicts can also happen during a rebase. The interactive rebase editor in Komitly includes real-time conflict prediction — as you reorder, squash, or drop commits, Komitly warns you which steps might produce conflicts. If a conflict does occur, the same 3-way merge editor opens, and you resolve it the same way.
In Komitly, you never have to manually search for <<<<<<<< markers. The 3-way merge editor shows both versions side by side with one-click resolution buttons. Combined with conflict prediction, you can anticipate and resolve conflicts faster than ever.Preventing conflicts
While conflicts are unavoidable in active teams, you can significantly reduce their frequency with a few habits:
- Pull frequently. The longer your branch lives without syncing, the more it diverges from the main branch. Pull from
mainat least once a day when working on a long-lived branch. - Keep branches short-lived. Merge your feature branches back quickly. A branch that lives for a week is far more likely to conflict than one that lives for a day.
- Communicate with your team. If two people are editing the same file, a quick message can save a lot of conflict resolution. Code ownership and task division help.
- Split large files. A 500-line file is a conflict magnet. Smaller, focused files reduce the chance of two people editing the same one.
- Use Komitly's conflict prediction. Before merging, check the merge preview to see if conflicts are expected. If they are, you can coordinate with your team or resolve them when you are ready, not when you are in the middle of something else.
Summary
Merge conflicts are a normal part of collaborative development. They follow a predictable pattern, and once you learn the steps, they become routine rather than frightening. Here is a quick recap:
- Conflicts happen when two branches modify the same lines in the same file.
- Git marks conflicts with
<<<<<<< HEAD,=======, and>>>>>>> branch-namemarkers. - To resolve: open the file, choose which version to keep (or combine both), remove the markers, stage with
git add, and commit. - Use
git merge --abortto cancel a merge and start over. - Komitly's 3-way merge editor shows both versions side by side with Accept Yours, Accept Theirs, and Accept Both buttons — no marker parsing required.
- Komitly's conflict prediction warns you about potential conflicts before you start a merge or rebase.
- Prevent conflicts by pulling frequently, keeping branches short-lived, and communicating with your team.
With conflicts demystified, you are ready to collaborate confidently. Next, learn how to put this all together in a complete workflow with your first pull request.