Resolving a merge conflict, without panicking
Summary: the merge conflict is the great nightmare of Git beginners. Yet it is a deliberate and benevolent mechanism: Git detects that it cannot decide on its own, and asks a human to arbitrate. This lesson explains why conflicts appear, how to read them, and gives the 5 steps to resolve them cleanly.
1. Why a conflict appears
Git automatically merges 95% of changes, as long as the modifications affect different areas of the code. A conflict appears only in one precise case: when two people modified the same line of the same file.
Crucial point: this is not a bug, it is a safety mechanism. Without Git, Alice's modification would silently overwrite Bob's (or vice versa). A reported conflict is a disaster avoided.
2. What a conflict looks like in a file
When Git detects a conflict, it modifies the file by inserting conflict markers that delimit the areas to arbitrate.
Here is what a conflicted file looks like:
server:
host: 0.0.0.0
port: 8080
<<<<<<< HEAD
timeout: 60
=======
timeout: 120
>>>>>>> feature/payment
database:
url: postgres://localhost/app
Decoding:
| Marker | Meaning |
|---|---|
<<<<<<< HEAD | Start of the current version (your target branch, often main) |
======= | Separator between the two versions |
>>>>>>> feature/payment | End of the incoming version (the branch you are merging) |
Between <<<<<<< HEAD and =======: what your current branch says.
Between ======= and >>>>>>>: what the incoming branch says.
Your job: decide which version to keep, or merge the two by hand, then remove all the markers.
3. The 5 steps to resolve a conflict cleanly
Do not panic. Always follow the same sequence.
Step 1 · Read — identify the areas
git status (or your editor's Git tab) shows the list of conflicted files. Open them one by one.
A file may contain several conflict areas — each one is delimited by its own <<<<<<< / ======= / >>>>>>> triplet.
Step 2 · Understand — the why of each version
Before choosing, take 30 seconds to understand why the two versions exist.
- Look at the name of the incoming branch (
feature/payment,hotfix/security) — the context gives a clue. - Look at who made the original commit (
git blame, or the author shown in the editor). - If doubt remains, go see the person concerned or ask on the team's Slack channel. No conflict deserves to be resolved blindly.
Step 3 · Arbitrate — four possible outcomes
For each conflict area, four outcomes are possible:
| Outcome | When to choose it |
|---|---|
| Keep the current version (HEAD) | The other branch's modification is obsolete or wrong |
| Keep the incoming version | Your version is obsolete or wrong |
| Combine the two by hand | Both modifications are legitimate and complement each other |
| Write a third version | Neither of the two is right, a synthesis is needed |
Most frequent case: combining the two. For example if Alice sets timeout: 60 and Bob sets timeout: 120, the real question to ask the team is "why must this timeout change?" — the answer dictates the right value, which may be neither 60 nor 120.
Step 4 · Clean up — remove the markers
No marker must remain in the final file. A search for <<<<<<< in your project must return zero results.
Tip: most modern editors (VS Code, JetBrains, Sublime) display conflicts with clickable buttons:
- "Accept Current Change" (keep HEAD)
- "Accept Incoming Change" (keep the incoming one)
- "Accept Both Changes" (combine)
- "Compare Changes" (visual diff)
These buttons remove the markers automatically after the choice.
Step 5 · Validate — test before committing
Before creating the merge commit, always run the tests. A badly resolved conflict may compile but break in production.
Once the tests are green, stage all the resolved files and create the commit. Git then generates a merge commit with a default message like Merge branch 'feature/payment' into main.
4. The three classic mistakes to avoid
Each of these three mistakes can be detected automatically:
- Mistake 1: enforce a code review on every merge — a colleague will reread and spot it.
- Mistake 2: configure your CI/CD to fail as soon as it detects
<<<<<<<in a file. - Mistake 3: make the tests mandatory in the GitHub/GitLab branch protection rules.
5. How to avoid conflicts, upstream
A conflict is always resolvable, but the best conflict is the one that never happens. Four simple habits divide their frequency by 10.
These habits are the real Git skill — not mastery of commands, but the team discipline that prevents conflicts from appearing in the first place.
6. The special case of rebase
There is a second situation where you encounter conflicts: during a rebase. A rebase "replays" your commits on top of another base — useful for keeping a linear history, but each replayed commit can create an individual conflict.
Important difference:
- A merge conflict: a single conflict to resolve, once for the whole merge.
- A rebase conflict: potentially one conflict per replayed commit. It can quickly become painful.
Recommendation for a beginner: prefer merge over rebase until you feel comfortable. Rebase is a powerful tool, but one that takes months of practice to master. It is covered in depth in the Premium Git Course.
7. In case of absolute doubt — the emergency exit command
If you are completely lost in the middle of a conflict, there is always an emergency stop button: cancel the ongoing merge and return to the previous state.
Concretely, the command is git merge --abort (or git rebase --abort in case of a rebase). It is completely safe: it destroys no commit, it only cancels the ongoing operation.
Remember: in Git, almost everything is reversible. A badly negotiated conflict will never ruin your day if you know this command.
Remember in 30 seconds
- A conflict appears only when two people modify the same line of the same file.
- It is not a bug, it is a safety mechanism — without Git, the modification would have been silently overwritten.
- Resolution follows 5 steps: read, understand, arbitrate, clean up, validate.
- Never leave a
<<<<<<<marker in a committed file. - Always re-run the tests after resolving a conflict.
- In case of panic, the cancel command brings everything back to the previous state.