Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 37

Resolving Merge Conflicts

Recommended resources

Hello! Welcome back to our module on version control with Git.

In our previous lessons, we've focused on creating and navigating the history of your project. You learned how to create parallel lines of development with branches and how to inspect the history using tools like git log and git diff. Now, we'll address an inevitable and perfectly normal part of working with branches: what happens when they diverge and then try to come back together in a way that Git can't figure out on its own.

This lesson will teach you how to handle one of the most initially intimidating, yet common, situations in Git: the merge conflict. Understanding how to confidently resolve these conflicts is a crucial skill for any developer or DevOps professional.

This lesson is dedicated to achieving the learning outcome: Resolve merge conflicts when combining divergent branches. We'll cover what causes them, the step-by-step process for resolving them on the command line, how modern tools can help, and how to handle them in a collaborative team setting.

1. What is a Merge Conflict?

A merge conflict is not an error; it's Git's way of saying, "I don't know how to combine these changes automatically, so I need a human to make the final decision." This typically happens when two different branches have modified the same lines in the same file, or when one branch deletes a file that another branch has modified.

Merging Changes in Git: When Contradictory Changes Happen
This diagram illustrates a common conflict scenario. After branching, both the main branch and a feature branch make different changes to the same line of code. When you try to merge, Git cannot automatically choose which change is correct, resulting in a conflict.

To understand the mechanics, it's helpful to know that Git performs a "three-way merge." It looks at three commits:

  1. The tip of your current branch (e.g., main).
  2. The tip of the branch you're merging in (e.g., feature-branch).
  3. Their most recent common ancestor.

If the changes in both branches are in different parts of the file, Git can usually merge them automatically. A conflict arises when both branches have made changes to the same part.

Resolve Git MERGE CONFLICTS: The Definitive Guide

To see this in action, watch this short segment from the video "Resolve Git MERGE CONFLICTS" by The Modern Coder. It gives a great visual explanation of the three-way merge and why conflicts occur.

Watch from 00:19 to 01:44. Focus on understanding that conflicts happen when Git cannot auto-merge changes made to the same part of a file on divergent branches.


2. The Conflict Resolution Workflow: A Hands-On Guide

The best way to learn how to resolve a conflict is to create one and fix it yourself. We'll walk through the entire process step-by-step.

Step 0: Let's Create a Conflict

Open your terminal in a practice directory and follow these commands. We'll create a repository, make a few commits, and then create two branches with conflicting changes.

# 1. Set up the initial repository
mkdir git-conflict-practice
cd git-conflict-practice
git init
echo "The first line of the file." > a_file.txt
git add a_file.txt
git commit -m "Initial commit with one line"

# 2. Create a feature branch and add a line
git checkout -b new-feature
echo "A new feature is added here." >> a_file.txt
git commit -am "Add feature line"

# 3. Go back to main and create a conflicting change
git checkout main
echo "An important update from main." >> a_file.txt
git commit -am "Add main's update line"

Now, the a_file.txt in the new-feature branch ends with "A new feature is added here.", while the main branch version ends with "An important update from main.". Both changes are on the second line. This is a recipe for a conflict.

Step 1: Attempt the Merge and Identify the Conflict

Let's try to merge new-feature into main. Since you are on the main branch, run:

git merge new-feature

You will see output similar to this:

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

Git has told you exactly what happened. Now, run git status. It will show you the conflicted file under an "Unmerged paths" section. This is your to-do list.

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:   a_file.txt

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

Step 2: Analyze the Conflict Markers

Now, open a_file.txt in a text editor. You will see something like this:

The first line of the file.
<<<<<<< HEAD
An important update from main.
=======
A new feature is added here.
>>>>>>> new-feature

These <<<<<<<, =======, and >>>>>>> are conflict markers. They show you the conflicting sections from the two branches.

  • <<<<<<< HEAD: This marks the beginning of the conflicting content from your current branch (main in this case, which is pointed to by HEAD).
  • =======: This separates the two conflicting blocks of code.
  • >>>>>>> new-feature: This marks the end of the conflicting content from the branch you are merging in (new-feature).

Resolve Git MERGE CONFLICTS: The Definitive Guide

The video from The Modern Coder explains these markers and the resolution process very clearly. Pay close attention to how the file is edited.

Watch the segment from 04:24 to 06:15. This is the core of the lesson. It demonstrates how to read the conflict markers, manually edit the file to the desired state, and then stage and commit the result.

Step 3: Resolve the Conflict (The Manual Part)

Your job now is to edit the file to be exactly how you want it to look after the merge. You must manually delete the conflict markers and decide which code to keep. You can:

  • Keep the HEAD version.
  • Keep the new-feature version.
  • Keep a combination of both.
  • Delete both and write something entirely new.

For our practice, let's decide to keep both lines. Edit a_file.txt so it looks like this:

The first line of the file.
An important update from main.
A new feature is added here.

Save the file.

Step 4: Finalize the Merge

You have resolved the conflict in the file. Now you just need to tell Git that you're done.

  1. Stage the resolved file: This tells Git that you have fixed the conflict for this file.
    git add a_file.txt
    
  2. Commit the merge: This finalizes the merge process. Git will create a new "merge commit."
    git commit
    
    Your text editor will open with a pre-populated commit message like Merge branch 'new-feature'. You can just save and close the editor to accept this message.

That's it! You've successfully resolved a merge conflict.

Test your understanding!

In a conflicted file, what is the purpose of the code between the ======= and >>>>>>> branch-name markers?

Show answer

That section of code represents the changes coming from the branch you are trying to merge into your current branch (in our example, the changes from the new-feature branch).

The Escape Hatch: Aborting a Merge

If you start a merge and realize you're not ready to resolve the conflicts, you can always return to the state before you started the merge with:
git merge --abort


3. Using Tools to Simplify Resolution

While editing files by hand is fundamental, most modern code editors have excellent built-in support for resolving merge conflicts, which is standard practice in a DevOps role.

Visual Studio Code, for example, will highlight the conflicted blocks and provide you with clickable actions like "Accept Current Change," "Accept Incoming Change," or "Accept Both Changes." This automates the process of editing the file and removing the markers.

Resolve Git MERGE CONFLICTS: The Definitive Guide

Let's see how much easier this is with a tool like VS Code. This short clip from The Modern Coder demonstrates the visual conflict resolution feature.

Watch from 06:15 to 07:12. Notice how the visual interface makes it much clearer to see the different versions and choose the one you want.

Even when using a visual tool, the final steps are the same: you must still git add the resolved file and git commit to finalize the merge.


4. Resolving Conflicts in a Real-World Workflow

The most common place you'll encounter conflicts is when working with remote repositories like GitHub, especially when creating Pull Requests.

Here's the typical scenario:

  1. You create a feature-branch from main.
  2. You work on your feature and push commits.
  3. In the meantime, a teammate merges their own changes into main.
  4. You create a Pull Request to merge your feature-branch into main, but GitHub reports a merge conflict because your teammate's changes conflict with yours.

Do not merge main into your branch directly on GitHub. The professional standard is to resolve this locally.

Git Branching and Merging - Detailed Tutorial

This detailed walkthrough from SuperSimpleDev is invaluable. It demonstrates the entire professional workflow for resolving a pull request merge conflict locally.

This is a crucial concept. Watch both segments: 40:17 - 48:54: This part sets up the realistic scenario where two pull requests from different engineers create a conflict. 48:54 - 53:36: This shows the step-by-step resolution. Pay close attention to the workflow: git checkout main, git pull, git checkout <your-branch>, git merge main, resolve conflicts, and finally git push.

The key workflow for resolving a remote conflict is:

  1. Make sure your local main branch is up-to-date:
    git checkout main
    git pull origin main
    
  2. Switch back to your feature branch:
    git checkout your-feature-branch
    
  3. Merge the updated main branch into your feature branch:
    git merge main
    
  4. This will trigger the conflict on your local machine. Resolve it using the process we learned earlier (edit, git add, git commit).
  5. Push your updated feature branch (which now contains the merge resolution) back to the remote:
    git push origin your-feature-branch
    

The Pull Request on GitHub will automatically update and show that the conflict is resolved, ready to be merged.


Conclusion

Merge conflicts can feel daunting at first, but they are a manageable and routine part of collaborative software development. By understanding the process, you can handle them with confidence.

Key Takeaways:

  • Merge conflicts occur when Git cannot automatically combine divergent changes made to the same part of a file.
  • The resolution workflow is always the same: Git reports a conflict, you manually edit the file to fix it (removing the <<<, ===, >>> markers), you stage the resolved file with git add, and you finalize the merge with git commit.
  • You can always git merge --abort to safely back out of a messy merge.
  • Modern IDEs like VS Code provide visual tools that significantly simplify the editing process.
  • For conflicts in pull requests, the standard practice is to pull the latest target branch (main) and merge it into your feature branch locally to resolve the conflict before pushing again.

In our next lesson, we will continue exploring how to manage and undo changes in Git. We will cover how to discard local, uncommitted changes using git checkout and how to safely reverse commits that have already been pushed using git revert.