Merge conflicts are a normal part of working with Git. They are not errors — they are Git's way of telling you that two branches made different changes to the same part of a file, and it needs your input to decide what the final version should look like. Once you understand how conflicts work and how to resolve them systematically, they stop being intimidating and become routine.
Why Conflicts Happen
Git performs merges automatically in most cases. When two branches modify different files or different parts of the same file, Git can combine the changes without any ambiguity.
A conflict arises when both branches modified the same lines of the same file in different ways. Git has no way of knowing which version you intended to keep — so it stops, marks the conflict in the file, and waits for you to decide.
What Git Does When a Conflict Occurs
When a merge produces a conflict, Git:
- Pauses the merge — it does not create a merge commit.
- Writes conflict markers into every conflicted file.
- Leaves the conflicted files in your working directory for you to edit.
- Waits for you to resolve the conflicts, stage the files, and complete the merge manually.
Running git merge on a conflicting branch produces output like this:
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
Until the conflict is resolved, the merge is considered in progress. Git holds a special state in .git/MERGE_HEAD that records this.
Checking the Conflict Status
At any point during a conflicted merge, git status shows which files need resolution:
git status
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: index.html
Files listed under "Unmerged paths" have conflicts. Files under "Changes to be committed" have already been resolved and staged.
Reading Conflict Markers
Git inserts conflict markers directly into the conflicted file to show you exactly where the disagreement is and what each branch contributed:
<<<<<<< HEAD
<div id="footer">contact: email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> feature-branch
Reading the markers:
| Marker | Meaning |
|---|---|
<<<<<<< HEAD | Start of the version from your current branch (the branch you are merging into) |
======= | Divider between the two versions |
>>>>>>> feature-branch | End of the version coming from the branch being merged in |
Everything between <<<<<<< HEAD and ======= is what your current branch has. Everything between ======= and >>>>>>> feature-branch is what the incoming branch has.
Resolving a Conflict Manually
Resolving a conflict means editing the file to produce the result you actually want — removing all three marker lines and leaving only the correct content.
You have three choices:
1. Keep your version (HEAD):
<div id="footer">contact: email.support@github.com</div>
2. Keep the incoming version:
<div id="footer">
please contact us at support@github.com
</div>
3. Combine both (the most common approach):
<div id="footer">
please contact us at email.support@github.com
</div>
Remove all marker lines — <<<<<<<, =======, and >>>>>>> — so that none of them remain in the file. Only the final intended content should be left.
Completing the Merge
Once you have resolved all conflicts in a file, stage it to mark it as resolved:
git add index.html
Staging the file is how you tell Git that the conflict in that file has been handled. After staging all conflicted files, git status confirms you are ready:
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Complete the merge by committing:
git commit
Git pre-fills a merge commit message. You can edit it to add notes about how conflicts were resolved — this is useful for collaborators who need to understand the merge later.
Using a Visual Merge Tool
For complex conflicts — especially files with multiple conflict regions — a visual merge tool is often easier than editing raw conflict markers. Git can launch one automatically:
git mergetool
Git opens a configured visual tool that presents three panels side by side:
- Left — your version (HEAD)
- Right — the incoming version
- Centre/bottom — the result you are building
After resolving each conflict in the tool, save and close. Git stages the resolved file automatically.
To see which merge tools Git supports on your system:
git mergetool --tool-help
To configure a preferred tool (for example, VS Code):
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
Aborting a Merge
If you start a merge, encounter conflicts, and decide you want to back out entirely — returning everything to the state before the merge started:
git merge --abort
This clears the merge state and restores your working directory to the pre-merge condition. All conflict markers are removed and the branch pointers are unchanged. Use this when you need more time to prepare before attempting the merge again.
Preventing Conflicts
Conflicts cannot always be avoided, but some practices reduce their frequency and severity:
- Merge or rebase frequently — the longer two branches diverge, the more likely they are to conflict when merged. Regularly pulling changes from the main branch into your feature branch keeps the histories close together.
- Keep commits small and focused — small commits that change one thing are less likely to overlap with changes on other branches.
- Communicate with your team — if you and a colleague are both working on the same file, coordinate to avoid editing the same sections simultaneously.
- Use short-lived branches — feature branches that stay open for days rather than weeks have far less opportunity to accumulate diverging changes.
A Conflict Resolution Workflow
The complete sequence from encountering a conflict to finishing the merge:
# 1. Attempt the merge
git merge feature-branch
# CONFLICT — Git pauses
# 2. See which files are conflicted
git status
# 3. Open and edit each conflicted file
# Remove all conflict markers, leave only the final content
# 4. Stage each resolved file
git add index.html
git add styles.css
# 5. Confirm all conflicts are resolved
git status
# "All conflicts fixed but you are still merging."
# 6. Complete the merge
git commit
Summary
| Command | What It Does |
|---|---|
git status | Shows which files have unresolved conflicts |
git add <file> | Marks a conflict as resolved by staging the file |
git commit | Completes the merge after all conflicts are resolved |
git mergetool | Opens a visual tool to resolve conflicts |
git merge --abort | Cancels the merge and restores the pre-merge state |