Skip to main content

Getting Started with Git · Chapter 5 / 5

Resolve merge conflicts

Conflicts scare many people, but they're normal. This chapter teaches you to read them and resolve them calmly, step by step.

Chapter 5 / 5

Step 01 / 13

In this chapter

In chapter 4, Git merged on its own. But sometimes it stops and asks for your help: that's a conflict. Good news: it's normal, it happens to everyone, and it's always resolved with the same method.

By the end of this chapter, you will be able to:

  • Explain why a conflict happens
  • Find the conflicted files with git status
  • Read the conflict markers in a file
  • Choose the right version: yours, the other one or a mix
  • Finish the merge with git add and git commit
  • Cancel a merge with git merge --abort

Step 02 / 13

What is a conflict?

Concept

Merge conflict: two branches changed the same part of the same file. Git doesn't know which version to keep, so it asks you to choose.

Imagine a shared document. You and a teammate edit the same sentence at the same time. The software can't guess which one to keep: it asks you to decide.

A conflict is not an error, and nothing is broken. It's Git telling you: "I can't decide for you".

Tip

Git merges on its own in the vast majority of cases: when branches touch different files, or different parts of the same file. A conflict only happens if the same line changed on both sides.

“A conflict means my repository is broken.” True or false?

Step 03 / 13

When does a conflict happen?

Let's take a concrete example with my-portfolio:

1

On main, the index.html file contains the title "Hello".

2

A teammate creates the feature/header branch and replaces "Hello" with "Welcome". They commit.

3

Meanwhile, on main, you replace "Hello" with "Bonjour". You commit.

4

You run git merge feature/header from main. The same line changed on both sides: conflict!

A
« Welcome »
B
feature
A
« Bonjour »
C
main

git merge → same line changed on both sides

Both branches changed the same line of the same file: Git can’t choose, so it asks you.

Git warns you right away:

$ git merge feature/header

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

Tip

A conflict can also show up during a git pull, since git pull merges your commits with the ones on GitHub. The resolution method is exactly the same.

Step 04 / 13

Find the conflicted files

First step: find out which files are involved. Your reflex, git status:

$ git status

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")

Conflicted files are in the Unmerged paths section, marked both modified (changed on both sides). Here, a single file: index.html.

Practice

During a conflict, Git guides you: read the lines in parentheses, they show the possible commands.

Step 05 / 13

Read the conflict markers

Open the conflicted file in your editor. Git added markers that show both versions, one above the other:

# Excerpt from index.html

<<<<<<< HEAD
<h1>Bonjour</h1>
=======
<h1>Welcome</h1>
>>>>>>> feature/header
<<<<<<< HEAD← your version (the branch you are on)

Bonjour

=======← the separator between the two versions

Welcome

>>>>>>> feature/header← the other branch’s version
Everything between the markers is yours to edit: keep one version, the other, or a mix, then delete all 3 markers.
  • <<<<<<< HEAD: the start of the conflict. Right below, your version, from the branch you're on (here main).
  • =======: the separator between the two versions.
  • >>>>>>> feature/header: the end of the conflict. Right above, the version from the other branch, whose name is shown.

Tip

To remember it: HEAD is where you are. The top part is yours; the bottom part is what comes from the other branch.

In a conflict, which marker separates YOUR version from the other branch's?

Step 06 / 13

Choose the right version

Resolving a conflict means writing the final version of the passage. You have three options:

  • Keep your version (the top one): you delete the bottom version.
  • Keep the other version (the bottom one): you delete the top version.
  • Combine both: you write a mix, for example <h1>Bonjour and welcome</h1>.

In every case, you also delete the three marker lines. For example, if you keep your version, the passage becomes:

# The same excerpt, once resolved

<h1>Bonjour</h1>

Tip

In VS Code, buttons appear above each conflict: Accept Current Change (keep your version), Accept Incoming Change (keep the other one), Accept Both Changes (keep both). They do the work for you, but always reread the result.

Practice

Before choosing, read both versions carefully. If it's not your code, ask the person who wrote it. Erasing a teammate's work without reading it is the worst way to resolve a conflict.

You chose the version to keep. What's left to do in the file?

Step 07 / 13

Finish the merge

Once all markers are gone from the file, tell Git the conflict is resolved with git add, then finish the merge with a commit:

$ git add index.html

$ git commit -m "Merge feature/header, keep the Bonjour title"

[main 4e9a1c7] Merge feature/header, keep the Bonjour title

Check that everything is in order:

$ git status

On branch main
nothing to commit, working tree clean

Tip

That's it! The merge commit is created and the conflict is behind you. You can see it with git log --oneline --graph.

You edited the conflicted file and removed the markers. What's next?

Step 08 / 13

Cancel a merge: git merge --abort

Lost in the middle of a conflict, or want to talk to your team first? You can cancel everything:

$ git merge --abort

Your repository goes back exactly to how it was before the git merge. Nothing is lost, on either side. You can run the merge again when you're ready.

Tip

git merge --abort only works during a merge in progress, before the final commit.

Which command cleanly cancels a merge in progress?

Step 09 / 13

Reduce conflicts

Conflicts are normal, but a few habits make them rarer and smaller:

  • Run git pull often: you work on the latest version.
  • Merge often: a branch that lives for three weeks drifts much further from main than a branch that lives for two days.
  • Make small, focused commits: fewer lines touched, fewer collisions.
  • Talk to your team: if you need to edit the same file, coordinate.
  • Split your code into small files: two people are less likely to touch the same one.

Step 10 / 13

Recap: resolving a conflict

1

git merge (or git pull) reports a CONFLICT

2

git status: you find the conflicted files (both modified)

3

You open each file, choose the version and delete the markers

4

git add: you mark each file as resolved

5

git commit: you finish the merge

Your cheat sheet for this chapter:

$ git status # find the conflicted files

$ git add <file> # mark a file as resolved

$ git commit -m "message" # finish the merge

$ git merge --abort # cancel everything, back to before the merge

git status
— Find the conflicted files
Edit the file
— Choose the version, remove the markers
git add
— Mark the file as resolved
git commit
— Finish the merge
git merge --abort
— Cancel everything

Step 11 / 13

Common mistakes

  • Leaving <<<<<<< markers in the code: the file no longer works. Search for <<<<<<< in your files before committing.
  • Running git add without rereading the file: check that the result is what you want.
  • Erasing the other person's work without understanding it: read both versions, and ask if needed.
  • Forgetting a file: as long as a file stays in Unmerged paths, Git refuses the commit. Run git status again.
  • Running git merge --abort every time out of fear: knowing how to cancel is useful, but resolving a conflict is a skill you learn quickly.

Step 12 / 13

Bonus: under the hood

Tip

Optional part, for the curious. You can skip straight to the quiz.

How does Git know there's a conflict? It doesn't compare two versions of the file, but three:

  • The version on your branch (HEAD)
  • The version on the other branch
  • The version of the common ancestor: the last commit both branches share, before they split

If a line changed on only one side compared to the ancestor, Git takes that change without hesitation. If it changed on both sides, differently, it's a conflict. This is called a three-way merge.

You can find the common ancestor of two branches:

$ git merge-base main feature/header

3f2a1b4c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a

Tip

To also see the ancestor's version inside the markers, turn on this setting: git config --global merge.conflictStyle zdiff3. A third part, marked |||||||, appears between your version and the other one. Handy to understand who changed what.

Step 13 / 13

Test your knowledge

Last quiz of the course: check that you can resolve a conflict. Click the answer that looks right: every answer is explained.

Quiz · Chapter 5

1. When does a merge conflict happen?

2. In a conflicted file, what is between <<<<<<< HEAD and =======?

3. How do you find the conflicted files?

4. You removed all the markers from index.html. What comes next?

5. What does git merge --abort do?

6. Which habit reduces the risk of conflicts?

Your feedback matters

Help us improve this course by sharing your thoughts.

So we can follow up if needed.