Previously, in Part 4, you split ClinicApp's timeline into parallel branches and merged add-notes-field back into master — and Git did it with a quiet little "fast-forward," no drama at all.

Today we deal with the drama. Merge conflicts are the number one reason people whisper "I'm scared of Git" — so we're going to cause one on purpose, in a safe playground, and discover it's about as dangerous as a sticky note. By the end of this part, a conflict will feel like Git politely asking for your opinion. Because that's exactly what it is.

Most merges are automatic

Here's the secret nobody tells beginners: the vast majority of merges involve no conflict at all. If your branch changed Patient.cs and another branch changed Home.razor, Git merges them without asking you anything. Even two changes in the same file merge cleanly, as long as they touched different lines.

How? Git performs a three-way merge. It looks at three snapshots: the base (the common ancestor commit where the two branches parted ways), yours (the tip of the branch you're on), and theirs (the tip of the branch you're merging in). For every line, Git asks: "who changed this compared to the base?" If only one side changed it, that change wins automatically. Easy.

ABCDE M merge commit has two parents
Merging joins two timelines: the merge commit M remembers both parents, and nothing from either branch is lost.

Notice the new commit at the top of the figure: a merge commit. Unlike every commit you've made so far, it has two parents — one on each timeline. That's how Git records "these two histories became one here." Compare that with Part 4's fast-forward, where master simply slid its label forward along an existing line of commits and no new commit was needed. A fast-forward is Git taking a shortcut; a three-way merge is Git tying a knot.

Let's break something on purpose

A conflict happens in exactly one situation: both sides changed the same lines since the base. Git has no way to know which version you want — it's a tool, not a mind reader. So let's manufacture that situation in your clone of the workshop repo.

Remember the last commit on master, "Polish the home page welcome text"? We're going to have two branches polish it again, in two different directions. First branch:

git switch master
git switch -c change-welcome-a

Open ClinicApp/Components/Pages/Home.razor, find the welcome line, and make it warmer — something like:

<p class="lead">Welcome to ClinicApp — caring for you, one visit at a time.</p>

Save and commit:

git add .
git commit -m "Make the welcome line warmer"

Now hop back to master and create a second branch — crucially, it starts from the old master, so it has never seen your warm version:

git switch master
git switch -c change-welcome-b

Edit the very same welcome line, but make it snappy instead:

<p class="lead">Welcome to ClinicApp! Book, browse, and breathe easy.</p>
git add .
git commit -m "Make the welcome line snappier"

Two timelines, one line, two opinions. Time to merge. The first one is uneventful — since master hasn't moved, Git just fast-forwards, exactly like Part 4:

git switch master
git merge change-welcome-a

Now merge the second branch. Type it and watch closely:

git merge change-welcome-b
Auto-merging ClinicApp/Components/Pages/Home.razor
CONFLICT (content): Merge conflict in ClinicApp/Components/Pages/Home.razor
Automatic merge failed; fix conflicts and then commit the result.

There it is. The message that makes grown developers spill their coffee. Take a breath — nothing is broken, nothing is lost, and every commit you've ever made is perfectly safe. Run git status and Git even tells you what it needs: the file is listed under "both modified," and the instructions say fix it and commit.

Reading the conflict, calmly

Open Home.razor. The welcome line has grown some strange decorations:

<<<<<<< HEAD
<p class="lead">Welcome to ClinicApp — caring for you, one visit at a time.</p>
=======
<p class="lead">Welcome to ClinicApp! Book, browse, and breathe easy.</p>
>>>>>>> change-welcome-b

Let's translate each region into plain words:

  • <<<<<<< HEAD — "everything from here down to the divider is what your current branch says." HEAD is Git's name for wherever you're standing right now — master, which already absorbed the warm version.
  • ======= — the divider. Yours above, theirs below. That's all it is.
  • >>>>>>> change-welcome-b — "everything from the divider up to here is what the incoming branch says," and it's even labeled with that branch's name.

That's the entire anatomy of a conflict. Git isn't broken, and it isn't angry. It merged everything it could, then stopped at the one spot where two humans disagreed and asked the only reasonable question: "You're the editor-in-chief. Which version goes to print?"

Resolving it: pick, blend, or rewrite

Your job is simply to make the file look the way it should look — and delete the marker lines. You can keep yours, keep theirs, or do what a good editor does: blend them. Let's blend:

<p class="lead">Welcome to ClinicApp — book, browse, and breathe easy.</p>

Make sure all three marker lines (<<<<<<<, =======, >>>>>>>) are gone, save the file, then tell Git you've made your editorial decision:

git add ClinicApp/Components/Pages/Home.razor
git commit -m "Merge change-welcome-b, blending both welcome lines"

Done. Run git log --oneline --graph and admire the little diamond shape: two timelines splitting apart and joining again at your brand-new merge commit — the one with two parents. You just resolved your first merge conflict, on purpose, with no casualties.

The no-shame exit

One more command for your back pocket. If you're ever mid-conflict and feel in over your head — the markers are confusing, you edited the wrong thing, whatever — you can simply walk away:

git merge --abort

This rewinds everything to the moment before you typed git merge, as if it never happened. No harm, no lost work, no shame. Take a walk, come back, and try again when you're ready. Knowing the exit exists is half of what makes conflicts stop being scary.

Tip: The best conflict strategy is prevention through rhythm: merge small and merge often. Two branches that drift apart for a week collide like freight trains; two branches that sync up daily bump like shopping carts. Small frequent merges mean small, easy conflicts — often none at all.

Your ClinicApp history now has branches, fast-forwards, a real merge commit, and one successfully negotiated disagreement. But it all still lives on your machine alone — one spilled coffee away from oblivion, and invisible to the world. In Part 6, we put your photo album in the cloud: GitHub, remotes, and your very first git push.