Resolve Merge Conflicts
Resolve merge conflicts with confidence in this Git Tutorial lesson — hands-on steps, troubleshooting, and what to study next.
Focus: resolve merge conflicts with confidence
You’re mid-sprint, you run git merge feature/login, and instead of a clean merge you’re staring at a wall of <<<<<<< HEAD marks. Your pulse quickens, you think about aborting, maybe even rewriting history. Sound familiar? Merge conflicts are the most feared Git ritual, but they’re also the most predictable — once you understand why they happen and how to read Git’s conflict markers, you’ll resolve them with the calm confidence of a senior engineer. In this lesson, you’ll learn to diagnose, resolve, and prevent merge conflicts — and even use them as a tool for intentional collaboration.
The problem this lesson solves
Merge conflicts happen to everyone, but most developers treat them as an emergency. The real problem is threefold: fear of breaking something, uncertainty about which version is correct, and lack of a repeatable process. When you panic, you make hasty edits, commit without testing, or — worse — git merge --abort and lose the integration work entirely.
Conflicts are not a sign that you’ve done something wrong. They’re Git’s way of saying "I can’t safely combine these two changes automatically — you need to make a decision." Once you reframe conflicts as decision points rather than errors, you can approach them with a clear head and a systematic process.
By the end of this lesson, you’ll be able to resolve merge conflicts with confidence — not by luck, but by understanding the underlying mechanics and applying a proven workflow every time.
Core concept / mental model
Think of a merge as combining two branches that have diverged from a common ancestor. Git tries to auto-merge changes that touch different lines, but when both branches modify the same lines, Git can’t guess your intent — it presents you with both versions and asks you to choose.
Here’s a mental model: imagine two editors editing the same paragraph in a shared document. If one changes the first half and the other changes the second half, a smart tool can combine them. But if both edit the exact same sentence differently, you need a human to decide which version (or a blend) is correct.
Git’s conflict markers are like highlighted comments in that shared document:
<<<<<<< HEAD— start of your current branch’s version=======— separator between the two versions>>>>>>> feature/login— end of the incoming branch’s version
Pro tip: Think of the conflict as a fork in the road, not a dead end. Git hands you the map and the keys — you just need to decide which path to take.
A critical concept is the merge base — the commit where the two branches last shared a common ancestor. Git compares each branch against that base. If only one branch changed a line, Git applies it automatically. If both changed it, you get a conflict.
How it works step by step
When you run git merge feature/login, Git follows this sequence:
- Find the merge base — the last commit common to both branches.
- Compute diffs — from the base to
HEAD(your branch) and from the base tofeature/login(incoming). - Attempt an automatic merge — if the diffs don’t overlap, Git merges cleanly.
- Detect overlaps — if the same lines are changed in both diffs, Git marks a conflict.
- Present the conflict — Git writes conflicted files with markers and stages them, but doesn’t complete the merge.
- Wait for your decision — you edit the files, stage them, and run
git committo finish the merge.
To resolve merge conflicts with confidence, follow this battle-tested workflow:
- Identify the conflicted files with
git status— they’re listed asboth modified. - Open each file and look for the
<<<<<<<markers. - Read the context around each conflict — don’t just pick one side blindly.
- Edit the file to produce a clean, correct version — remove all markers.
- Test your changes — run your test suite or build.
- Stage the resolved file with
git add <file>. - Commit the merge —
git commit(Git provides a default merge message).
Cause and effect: if you skip step 5, you might introduce a bug that passes the merge but breaks production. If you forget to remove all markers, Git won’t let you commit until you do — that’s a safety net, not an annoyance.
Hands-on walkthrough
Let’s walk through a realistic conflict from start to finish.
Step 1: Set up a demo repository
mkdir conflict-demo
cd conflict-demo
git init
git config user.email "you@example.com"
git config user.name "Your Name"
echo "function greet() {
console.log('Hello, world!');
}" > app.js
git add app.js
git commit -m "Initial commit"
Step 2: Create a branch and change the same line
git checkout -b feature/greeting
# Change 'Hello, world!' to 'Hello, Python!'
sed -i "s/Hello, world!/Hello, Python!/" app.js
git add app.js
git commit -m "Change greeting to Python"
# Switch back to main and change the same line differently
git checkout main
sed -i "s/Hello, world!/Hello, Git!/" app.js
git add app.js
git commit -m "Change greeting to Git"
Step 3: Attempt the merge — it will conflict
git merge feature/greeting
Output (abbreviated):
Auto-merging app.js
CONFLICT (content): Merge conflict in app.js
Automatic merge failed; fix conflicts and then commit the result.
Step 4: Inspect the conflict
git status
cat app.js
You’ll see:
function greet() {
<<<<<<< HEAD
console.log('Hello, Git!');
=======
console.log('Hello, Python!');
>>>>>>> feature/greeting
}
Step 5: Resolve the conflict by editing the file
# Edit to keep both? Or choose one? Let's keep the Python version.
cat > app.js << 'EOF'
function greet() {
console.log('Hello, Python!');
}
EOF
Step 6: Stage and commit
git add app.js
git commit -m "Merge feature/greeting with confidence"
Now check the log:
git log --oneline --graph
You should see a merge commit that ties both branches together.
Pro tip: Use
git merge --abortanytime you feel overwhelmed — it resets you to a clean state without losing your branch history. But don’t use it as a crutch; once you know the process, resolving is faster than aborting.
Compare options / when to choose what
When you hit a conflict, you have several resolution strategies. Here’s a comparison:
| Strategy | Command / Tool | When to use | Pros | Cons |
|---|---|---|---|---|
| Manual edit | Any text editor | Most conflicts | Full control, no new tools | Requires careful reading of markers |
| Keep ours | git checkout --ours <file> |
Your branch’s version is correct | Fast, no editing | Discards incoming changes forever |
| Keep theirs | git checkout --theirs <file> |
Incoming branch is correct | Fast, no editing | Discards your changes |
| Visual merge tool | git mergetool (e.g., VS Code, Beyond Compare) |
Complex conflicts with many hunks | Shows diff side-by-side, easier to blend | Requires setup and familiarity |
| Rebase instead | git rebase |
Clean linear history, or you control the branch | Avoids merge commits, can reduce conflicts in the long run | Changes history — risk on shared branches |
The golden rule: never resolve a conflict by blindly choosing one side unless you’ve verified the context. Prefer manual editing and running your tests — that’s the honest way to resolve merge conflicts with confidence.
Use git mergetool when you have a GUI available and the conflict spans multiple hunks — your brain handles visual diffing faster than text markers. Use git checkout --ours only when you know the incoming branch is obsolete.
Troubleshooting & edge cases
“I resolved the conflict, but git commit says I still have unresolvable conflicts.”
This happens when you left markers in the file. Run grep -n '^<<<<<<<' <file> to find remaining markers, fix them, and git add again.
“I used git checkout --theirs but the file still has conflict markers.”
That command works only while the merge is in progress before you edit the file. If you’ve already edited, run git checkout --theirs <file> again — it will overwrite your edits. Use with caution.
“My merge succeeded but the code is broken now.”
You probably resolved the conflict syntactically but not semantically. Always run your test suite after resolving a conflict. A merge conflict is a red flag that logic might be missing.
“I accidentally resolved the wrong file and want to start over.”
No need to panic. git checkout --conflict=merge <file> resets that file to its conflicted state. Or use git merge --abort to abort the entire merge and start fresh.
"Conflicts only happen in text files — binary files are easy."
Binary files (images, PDFs) are harder — Git can’t merge them. You get a conflict and must choose one version or use a specialized tool. git checkout --ours/--theirs is the common fix.
Another edge case: conflicts during git rebase — the process is similar, but instead of a merge commit, you resolve the conflict, run git add, then git rebase --continue. Never commit manually during a rebase.
What you learned & what's next
You’ve learned that merge conflicts are not emergencies — they’re decisions. You now know how to read conflict markers, walk through a systematic resolution workflow, and choose the right strategy for each situation. You can safely resolve simple conflicts, use --ours/--theirs when appropriate, and know how to reset when things go wrong.
Every learning objective is covered: you can explain the core idea (conflicts arise from overlapping changes that need human judgment) and you’ve completed a practical exercise that demonstrates a full conflict resolution.
What’s next? In the next lesson in this Git Tutorial, you’ll learn to undo mistakes with git revert and git reset — essential skills to pair with conflict resolution. You’ll also explore rebase strategies to minimize future conflicts. Ready to become a Git master? Dive in — you’ve got the confidence now.
Practice recap
Create a fresh repo, make a conflicting change on two branches, and resolve it using the steps in this lesson. Try both git merge and git rebase approaches, and use git status to observe the state. Then, reset with git reset --hard and repeat until you can resolve without looking at this page.
Common mistakes
- Panicking and running
git merge --abortat the first sign of conflict, losing the integration progress — try resolving instead; abort is a last resort. - Blindly choosing
--oursor--theirswithout reading the surrounding code, which can silently drop crucial logic — always inspect the full context. - Forgetting to run tests after resolving a conflict — a syntactically clean file can still be semantically broken; always verify with your test suite.
- Leaving conflict markers (
<<<<<<<,=======,>>>>>>>) in the file and trying to commit — Git will refuse, so usegrepto find and remove them. - Using
git commitduring a rebase conflict instead ofgit rebase --continue, which corrupts the rebase state.
Variations
- Use
git mergetoolwith VS Code or other GUI tools for a visual side-by-side diff when conflicts are complex. - Replace
git mergewithgit rebaseto avoid merge commits and potentially reduce conflicts, but only on private branches. - Try
git rerere(reuse recorded resolution) to automatically apply your conflict resolutions in future merges.
Real-world use cases
- A team of five developers frequently works on the same files; understanding conflicts prevents merge-phobia and accelerates PR reviews.
- An open-source maintainer must integrate many community PRs daily — confident conflict resolution ensures timely releases.
- A freelancer manages multiple client branches and merges them into a shared codebase; quick resolution minimizes downtime and billing disputes.
Key takeaways
- Merge conflicts are decision points, not errors — Git needs your judgment when both branches change the same lines.
- Read conflict markers carefully:
<<<<<<< HEADis yours,>>>>>>>branch name is theirs,=======separates them. - Follow a systematic workflow: inspect with
git status, edit to remove markers, test, stage, and commit. - Use
git checkout --ours/--theirsonly when you fully understand the consequence — avoid blind choices. - Always run your test suite after resolving a conflict to catch semantic breakage.
- For rebase conflicts, resolve,
git add, thengit rebase --continue— never commit manually.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.