EduFlow
Git & GitHub
0%

Section 2 · Branching and Merging

Resolving Merge Conflicts Step by Step

17 min4 min readPut in order

Lesson at a glance

Read a merge conflict calmly, edit the conflict markers into the result you want, mark files resolved and finish the merge, or abort it and start over.

  1. 1What Git tells you
  2. 2Reading the markers
  3. 3Resolving it, step by step
  4. 4Bailing out
  5. 5Making conflicts easier to read

No video here — just the real thing: a written lesson, runnable examples, a quiz and practice.

Sooner or later two branches change the same line. You change your tagline on main to “Front-end developer in Lagos.” while your tagline branch, started earlier, rewrote the same line to “Front-end developer who loves accessible UI.” Git can’t know which is right, so it stops and asks. That’s all a merge conflict is: a question. I’ve helped hundreds of people through their first one, and the panic always comes from the unfamiliar markers, never from the actual problem.

What Git tells you

Terminal
git switch main
git merge tagline
Text
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

You’re now in the middle of a merge. Any files that merged cleanly are already staged. Run git status to see the rest:

Text
On branch main
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   index.html

no changes added to commit (use "git add" and/or "git commit -a")

Read that output; it’s the whole procedure. Fix the conflicts, mark each file resolved with git add, then git commit. Or abort.

Reading the markers

Open index.html. Git has written both versions into the file, fenced by markers:

index.html
    <h1>Maya Okafor</h1>
<<<<<<< HEAD
    <p>Front-end developer in Lagos.</p>
=======
    <p>Front-end developer who loves accessible UI.</p>
>>>>>>> tagline
  • The top half, from the opening marker labelled HEAD down to =======, is your side: the branch you’re on, here main.
  • The bottom half, from ======= down to the closing marker labelled tagline, is their side: the branch you’re merging in.

Everything outside the markers merged without trouble. A file can contain several of these blocks, so search the file for the opening marker (seven less-than signs) until there are none left.

The merge base says 'Front-end developer in progress.' Main changed it to 'in Lagos.' The tagline branch changed it to 'who loves accessible UI.' Both sides changed the same line, so Git cannot choose and you write the result by hand. Merge base "…developer in progress." HEAD (main) "…developer in Lagos." tagline "…loves accessible UI." Same line changed twice: you decide
Git compares both sides with the merge base

Resolving it, step by step

1. Decide what the result should be. Not “which side wins” by reflex; what should the page actually say? Often it’s a combination. Here, both facts are good:

index.html
    <h1>Maya Okafor</h1>
    <p>Front-end developer in Lagos who loves accessible UI.</p>

2. Remove every marker. The three marker lines must go. Git doesn’t read the file to check; it’s your job.

3. Check the result. Open the page in a browser, run your tests (npm test once the portfolio has them), and run:

Terminal
git diff --check

It warns about any leftover conflict markers. Five seconds well spent.

4. Mark it resolved and finish.

Terminal
git add index.html
git status        # "All conflicts fixed but you are still merging."
git commit        # editor opens with "Merge branch 'tagline'"; save and close

git merge --continue does the same as that final git commit. The merge commit now has two parents, like any other.

If you know one side should win for a whole file, skip the editing: git restore --ours index.html keeps your branch’s version and git restore --theirs index.html keeps the incoming one. Then git add it as usual.

Bailing out

If a conflict is bigger than you expected, or you merged the wrong branch, you can always retreat:

Terminal
git merge --abort

Your branch, index and files go back to exactly how they were before git merge. Nothing is lost. It’s often smart to abort, update or tidy the branch, and try again with a clear head.

The same markers and the same fix-add-continue routine appear whenever Git combines two versions of a line: during a rebase, when you apply a stash, and when git pull merges someone else’s work into yours. Learn the routine once here and every later conflict in this course will look familiar. Only the command you use to continue or abort changes.

Making conflicts easier to read

By default you see only the two sides. Ask Git to show the original lines too:

Terminal
git config --global merge.conflictStyle zdiff3

Now each conflict has a third section between ||||||| and ======= showing the merge base. Seeing what the line was before either change usually makes the right answer obvious: you can see what each side meant to do, not only what it ended up with.

Editors help too. VS Code highlights each block with buttons such as Accept Current Change, Accept Incoming Change and Accept Both Changes, plus a three-way merge editor. Use them, but read the result; Accept Both often produces two <p> tags where you wanted one.

Merging is one way to combine histories. Next you’ll meet the other, rebasing, and the one rule that keeps it safe.

Key takeaways

  • A conflict means both branches changed the same lines since their merge base, so Git asks you to choose; nothing is lost or broken.
  • Between <<<<<<< and ======= is your current branch (HEAD); between ======= and >>>>>>> is the branch being merged in.
  • Resolve by editing the file into its final form, removing every marker, then git add the file and git commit.
  • git merge --abort puts everything back exactly as it was before the merge started.
  • Setting merge.conflictStyle to zdiff3 also shows the original lines, which makes most conflicts easy to judge.

Further reading

Check your understanding

4 questions

Question 1 of 4

You’re on main and ran git merge tagline. In index.html you see:

Text
<<<<<<< HEAD
<p>Front-end developer in Lagos.</p>
=======
<p>Front-end developer who loves accessible UI.</p>
>>>>>>> tagline

Which line came from main?

Question 2 of 4

You’ve edited index.html so it reads the way you want and every marker is gone. git status still lists it under “Unmerged paths”. What’s the next step?

Question 3 of 4

Halfway through a messy conflict you realise you merged the wrong branch. How do you get back to exactly where you were before the merge?

Question 4 of 4

Your branch has merged and pushed, and a teammate finds ======= printed on the live home page. Which habit would have caught this before committing?

Practice

Put in order

Resolve the tagline conflict

You’re on main and want the tagline branch merged in. Put the steps in the order you’d run them to get from the conflict to a finished merge commit.

Use the arrow buttons to reorder.

  1. 1Run git merge tagline and see CONFLICT (content): Merge conflict in index.html.
  2. 2Run git add index.html to mark the conflict resolved.
  3. 3Run git commit to record the merge commit.
  4. 4Write the final tagline and delete the three marker lines.
  5. 5Open index.html and find the <<<<<<< block.
  6. 6Run git diff --check and view the page in a browser.
  7. 7Run git status to list the unmerged paths.