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

Merge Conflict Definition

Merge conflicts (a.k.a. “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. The most common cause of a merge conflict is when you and a collaborator both edit the same lines in the same file and one of you pushes without first pulling the most recent version from GitHub.

For a visual demonstration of this, see the graphic below. Note that though this has visual similarity to the workflow diagrams that can be found throughout this website 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

General Conflict Resolution Strategy

If you encounter a conflict, Git will combine your local version of the conflicted file with its equivalent in GitHub. In order to resolve the conflict, you’ll need to manually tweak the local file(s) to decide what the script should look like then commit/push that file as normal.

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

Fixing Conflicts

In order to make this discussion more grounded, we will demonstrate how a conflict can be repaired after one has been encountered. For context, the conflict shown below was caused by editing a file on GitHub (lyon-script.r), then editing the same line of that same file locally in our IDE and pushing without pulling first. If we had pulled before committing our local change, there would be no conflict!

After we attempt to push our local commit in RStudio, we get an intimidating dialog that looks like the following image. If we look at the lines of that message that start with hint: you can see that RStudio is warning us about why the push failed and how to go about fixing it in reasonably human-readable terms.

Screen capture of RStudio message warning about a merge conflict

Let’s follow RStudio’s advice and pull the latest changes from GitHub. This will cause another scary dialog about how the ‘automatic merge’ failed but this means we are on the road to a resolution.

Screen capture of RStudio message warning about post-merge conflict auto-merge failure

If we look at the offending file, we’ll see a horrible-looking chimera file of the version we had locally versus what it looked like on GitHub before we attempted to push. You will see that Git inserted a line of <<<<, ====, and >>>> to encapsulate the version of the original lines we had locally versus what was on GitHub respectively.

Screen capture of RStudio where a conflicted file has been auto-merged by GitHub

NoteFinding Conflicts in Long Scripts

These weird special lines can make finding merge conflicts in longs scripts much easier! Simply use your IDE’s search function to look for four <<<< next to one another as it is unlikely such a line would normally be included in your code.

Once Git has combined the two versions of the file, it is up to us to read through the script and edit it so that it looks right to us. At a minimum, this involves deleting the weird lines (in the screen capture below they are liens 1, 5, and 8) but in more difficult cases you may need to consider which version of the line is the one you want to retain.

In this case, we can retain both lines of code without damaging either so let’s just delete the special character lines.

Screen capture of a script in RStudio where the merge conflict lines have been removed

Once you are confident you’ve fixed the conflict, commit the changes you made to resolve the conflict. This is done in the same way that you’d normally make a commit.

Screen capture of a commit in RStudio with the message 'fixing conflict'

Before you push, take note that the Git pane is telling you that you are two commits ahead of ‘origin/main’. This is because both your original commit and your second commit (fixing the conflict) have yet to be pushed back up to GitHub–your first push failed because of the merge conflict. Once you’ve noted that, push your changes.

Screen capture of a script in RStudio where the merge conflict lines have been removed

Your RStudio should now look how it did before you got the conflict and you can continue working normally–hopefully having learned a lesson in proactive communication with your collaborators.

Screen capture of RStudio with an open script

After we attempt to sync our local commit in Positron, we get an intimidating warning about a merge conflict (see pop-up in the bottom right) and our script header is filled with gross special chacters in red text.

Screen capture of Positron message warning about a merge conflict

Because Positron’s default Git interaction is “sync” (a combination of a push and a pull) the local version of our script and the version on GitHub have already been auto-merged by Git. This means we are on the road to a resolution.

If we look at the offending file, we’ll see a horrible-looking chimera file of the version we had locally versus what it looked like on GitHub before we attempted to push. You will see that Git inserted a line of <<<<, ====, and >>>> to encapsulate the version of the original lines we had locally versus what was on GitHub respectively.

NoteFinding Conflicts in Long Scripts

These weird special lines can make finding merge conflicts in longs scripts much easier! Simply use your IDE’s search function to look for four <<<< next to one another as it is unlikely such a line would normally be included in your code.

Once Git has combined the two versions of the file, it is up to us to read through the script and edit it so that it looks right to us. At a minimum, this involves deleting the weird lines (in the screen capture below they are liens 1, 5, and 8) but in more difficult cases you may need to consider which version of the line is the one you want to retain.

Positron also helpfully provides buttons over each merge that allow us to quickly choose which version of the code we want but we could also edit the script manually.

In this case, we can retain both lines of code without damaging either so let’s just delete the special character lines.

Screen capture of a script in Positron without merge conflict lines

Once you are confident you’ve fixed the conflict, commit the changes you made to resolve the conflict. This is done in the same way that you’d normally make a commit. Note you will likely want to replace the default merge conflict commit message with something that is more human-readable.

Screen capture of a commit in Positron with the message 'fixing conflict'

Before you sync, take note that the “Sync Changes” button is telling you that you have two changes to contribute. This is because both your original commit and your second commit (fixing the conflict) have yet to be pushed back up to GitHub–your first push failed because of the merge conflict. Once you’ve noted that, sync your changes.

Screen capture of a script in Positron where the merge conflict lines have been removed

Your Positron should now look how it did before you got the conflict and you can continue working normally–hopefully having learned a lesson in proactive communication with your collaborators.

Screen capture of Positron with an open script

Avoiding 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
  • Pull early and often
  • Push your commits frequently (always pulling before pushing!)