Merge conflicts are one of those things every developer runs into—usually at the worst possible moment. You pull the latest changes, try to merge your branch, and Git throws a conflict at you. It’s not broken, it’s just Git asking you to make a decision.
Let’s walk through what’s actually happening, how to resolve conflicts in GitHub, and how to reduce how often they show up in the first place.
What a Merge Conflict Really Means
A merge conflict happens when Git can’t automatically reconcile differences between two branches. Typically, this occurs when the same lines in a file were changed in different ways.
For example, imagine two developers edit the same function:
1// main branch
2function calculateTotal(price) {
3 return price * 1.2;
4}
5
6// feature branch
7function calculateTotal(price) {
8 return price * 1.15;
9}When merging, Git doesn’t know which version is correct—so it asks you to decide.
How Git Marks Conflicts
When a conflict occurs, Git modifies the file and inserts markers:
1<<<<<<< HEAD
2return price * 1.2;
3=======
4return price * 1.15;
5>>>>>>> feature-branchHere’s how to read this:
- HEAD: your current branch
- feature-branch: the branch you're merging in
- The section between them is the conflict you must resolve
Resolving Merge Conflicts Step by Step
Here’s a typical workflow when handling merge conflicts in GitHub locally:
1. Pull and Attempt Merge
1git pull origin mainIf conflicts exist, Git will pause the merge.
2. Open Conflicted Files
Look for files marked as "both modified":
1git status3. Edit and Resolve
Manually choose or combine the correct code. Remove the conflict markers.
1function calculateTotal(price) {
2 return price * 1.18; // agreed updated logic
3}4. Mark as Resolved
1git add .5. Complete the Merge
1git commitGit will create a merge commit with your resolution.
Handling Conflicts Directly in GitHub UI
If you’re working with pull requests, GitHub often detects conflicts before merging.
In the PR view, you might see:
This branch has conflicts that must be resolved
Click Resolve conflicts, and GitHub provides an inline editor. You can:
- Edit conflicting sections
- Remove markers
- Mark the resolution complete
This works well for small conflicts, but for larger ones, local resolution is safer.
Merge vs Rebase: Conflict Experience
Conflicts feel different depending on your workflow.
Using Merge
- Conflicts happen once during merge
- History remains intact
Using Rebase
- Conflicts may happen multiple times (per commit)
- History becomes linear
Example rebase flow:
1git checkout feature-branch
2git rebase mainIf conflicts occur:
1git add .
2git rebase --continueRebasing can feel more tedious during conflicts, but often results in a cleaner commit history.
A Common Mistake Developers Make
Trying to "just accept one side" without understanding the change.
This works sometimes—but can silently break functionality. Instead:
- Read both versions carefully
- Understand intent
- Combine logic when needed
Reducing Merge Conflicts (Preventive Strategies)
You won’t eliminate conflicts entirely, but you can make them far less frequent.
1. Keep Branches Short-Lived
The longer a branch lives, the more likely it diverges.
2. Pull Frequently
1git pull origin mainDo this daily (or more) on active branches.
3. Break Large Changes Into Smaller PRs
Smaller changes reduce overlap with other developers.
4. Communicate Early
If two people are editing the same file, coordinate instead of colliding later.
5. Use Code Ownership
Define clear ownership of modules or files to reduce overlap.
When Conflicts Get Messy
Sometimes conflicts span dozens of files. At that point:
- Use a visual merge tool (VS Code, IntelliJ, etc.)
- Compare changes side-by-side
- Test thoroughly after resolving
Example: launching VS Code merge editor
1code .Most modern editors highlight conflicts clearly and provide "Accept Incoming" or "Accept Current" options.
Quick Sanity Checklist After Resolving
- Project builds successfully
- Tests pass
- No leftover conflict markers
- Behavior matches expectations
Final Thought
Merge conflicts aren’t a failure—they’re a signal. Git is telling you two changes need human judgment. Once you understand how to read and resolve them, they become routine rather than frustrating.
The real win isn’t just fixing conflicts—it’s designing your workflow so they rarely happen in the first place.