Conflicts

Module Learning Objectives

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

  • Describe the causes of merge conflicts
  • Explain how to avoid merge conflicts
  • Summarize what to do if a merge conflict occurs

What is a Merge Conflict?

Merge conflicts are a normal part of the Git workflow so don’t get discouraged when you run into them! They occur when Git cannot figure out how to automatically merge new changes together. This can happen when you and your collaborators change the same lines in the same file without first pulling the changes that the other party has made.

Brief Overview of Merge Conflict Workflow

So the basic steps to resolving a merge conflict using RStudio are as follows:

  1. When a conflict happens, your local file will automatically be modified to include both possible lines (wrapped in some formatting characters described in greater detail below)

  2. Edit the lines in your file(s) that caused the merge conflict to your desired status

  3. Commit those changes

  4. Push your changes to GitHub

We can see those steps visually in the following workflow diagram:

Graphic indicating the process of resolving a conflict when one occurs. After the initial conflict (caused when pushing a file from your machine differs from the GitHub version of that file), the combined file is auto-generated on your machine and you must then resolve the changes manually. These changes can then be committed and pushed up to GitHub

How Merge Conflicts Happen

Below is a common scenario that can lead to merge conflicts and then the steps to address a conflict when it occurs.

Let’s say we have a repository that we’ve shared with a collaborator. Currently there’s a README.md and only one script, test-script.R, in it.

Screenshot of a simple GitHub repository containing only a single script and a README

test-script.R contains one line. Suppose we want to work on this script and add more lines to it.

Screenshot of a script with a single comment line

Let’s go commit our edits. The green lines highlight the fact that we’ve added two new lines to our script, lines 2 and 3. We type out our commit message, and click Commit.

Screenshot of a staged file with a commit message where a vector of bird names is being added

Great! The message “Your branch is ahead of ‘origin/main’ by 1 commit” lets us know that everything is proceeding smoothly. Suppose that we decided to take a break and stepped away from our computer.

Screenshot of RStudio after a successful commit

Then, unbeknownst to us, our collaborator made their edits to the same script and committed and pushed their changes to the GitHub repository. At the moment, here is what the shared repository looks like.

Screenshot of the earlier GitHub repository where someone has made edits to the script

When we get back to our computer, we’re ready to push our changes to GitHub, but an error shows up. Basically, it is telling us that our GitHub repository contains changes that we do not have on our local computer. To remedy this, the message suggests that we pull the changes from GitHub to our machine to catch our local machine back up.

Screenshot of the message you get when a push is rejected because of a conflict

After clicking Pull, we get a new error message: “Merge conflict in test-script.R”.

Screenshot of the message you get when you pull after getting a conflict and Git (through RStudio) warns you that it created an automatic merge

Looking closer, the merge conflict prompted a new version of test-script.R to pop up. This version contains our edits and our collaborator’s edits, along with the delimiter lines that start with <<<<<<<, =======, and >>>>>>>. Git is urging us to manually fix the conflicted lines before continuing.

Screenshot of a script where there was a conflict now having rows of symbols separating the two versions of the conflicting line

Our file now has an U icon, which stands for an unresolved merge conflict.

Screenshot of Rstudio's Git pane where the script with conflict now has two orange 'U' icons (for 'unresolved')

In general terms the steps that come before a merge conflict are displayed in the visual below. Note that though this has visual similarity to the workflow diagrams throughout this bookdown we do not recommend intentionally causing a merge conflict :)

Graphic of three vertical rectangles, the left and right ones labeled 'you' and 'other' while the center has a happy cloud emoji. Both side rectangles pull a given file from Github then edit that file in different ways. The first person is able to successfully push without issue but the second person to push gets a conflict

Resolving Merge Conflicts

So how do we resolve this merge conflict? We need to edit the script so that it looks like how we want it. We can either pick our lines to keep, our collaborator’s lines, some combination, or something new altogether. Be sure to communicate with your collaborator to discuss exactly how it should be fixed. After merging the changes wherever appropriate, delete the delimiter lines.

Screenshot of the script where the special characters have been removed and the conflict has been resolved

Then stage, commit the changes, and push them to GitHub!

Screenshot of RStudio where the once-conflicted script is being staged and committed with issues resolved

Perfect! We’ve fixed the merge conflict!

Screenshot of the success message from RStudio when a push works as desired

Let’s check back on the shared repository. The latest commit shows that we’ve successfully pushed our changes to GitHub.

Screenshot of a GitHub repository with the the repaired file included

Screenshot of the repaired file in Github showing the latest changes

Navigating to the commit history, we see that first we committed our changes, then our collaborator committed and pushed their changes, causing a merge conflict since we were editing the same lines in the same file. To resolve this, we edited those lines directly in our RStudio and committed and pushed our changes once more. Finally, the merge conflict is resolved and all the necessary changes are merged.

Screenshot of the commit history of the GitHub repository showing where the conflict appears in the history

Tips on Avoiding Merge Conflicts

Merge conflicts aren’t exactly fun, so here are some tips to avoid them:

  • Communicate with your team members often to avoid working on the same files at the same time! Let each other know who is working on what
  • Commit frequently and in small chunks
  • Try pulling before committing