Conflicts

Overview

Teaching: 15 min
Exercises: 0 min
Questions
  • What do I do when my changes conflict?

Objectives
  • Explain what conflicts are and when they can occur.

  • Understand how to resolve conflicts resulting from a merge.

As soon as people can work in parallel, they’ll likely step on each other’s toes. This will even happen with a single person: if we are working on a piece of software on both our laptop and a server in the lab, we could make different changes to each copy. Version control helps us manage these conflicts by giving us tools to resolve overlapping changes.

To see how we can resolve conflicts, we must first create one. The file mars.txt currently looks like this in our planets repository:

$ cat mars.txt
Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity

Let’s create a new branch for discussing Mars’ temperature and checkout that branch.

$ git branch marsTemp

But before we make changes related to Mars’ temperature in the marsTemp branch, let’s add a line to Mars.txt here in the main branch.

$ nano mars.txt
$ cat mars.txt
Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity
I'll be able to get 40 extra minutes of beauty rest

and commit that change to the main branch

$ git add mars.txt
$ git commit -m "Add a line about the daylight on Mars."
[main 5ae9631] Add a line about the daylight on Mars.
 1 file changed, 1 insertion(+)

We can then examine the commit history of the main branch.

$ git log --oneline
5ae9631 Add a line about the daylight on Mars.
005937f Discuss concerns about Mars' climate for Mummy
34961b1 Add concerns about effects of Mars' moons on Wolfman
f22b25e Start notes on Mars as a base

Now that we’ve made our changes in the main branch, let’s get to work on our comments about the temperature in the marsTemp branch.

$ git checkout marsTemp
$ git branch
* marsTemp
  main

Let’s make a note in mars.txt about the temperature. Note that when we open this file the line we added about the daylight on Mars will not be present as that change is not part of this branch.

$ nano mars.txt
$ cat mars.txt
Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity
Yeti will appreciate the cold

Now let’s commit this change to the marsTemp branch

$ git add mars.txt
$ git commit -m "Add a line about the temperature on Mars"
[main 07ebc69] Add a line about the temperature on Mars
 1 file changed, 1 insertion(+)

Again, we can look at the history of this branch.

$ git log --oneline
07ebc69 Add a line about the temperature on Mars
005937f Discuss concerns about Mars' climate for Mummy
34961b1 Add concerns about effects of Mars' moons on Wolfman
f22b25e Start notes on Mars as a base

Notice that the commit related to Mars’ daylight is not present as it is part of the main branch, not the marsTemp branch.

Now that we’ve added changes about the temperature we can merge them into the main branch. First, let’s checkout the main branch.

$ git checkout main
$ git branch
  marsTemp
* main

And then merge the changes from marsTemp into our current branch, main.

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

Review the status of the repository now that we’ve been told merging has resulted in a conflict.

$ git status
On branch main
You have unmerged paths.
  (fix conflicts and run "git commit")

Unmerged paths:
  (use "git add <file>..." to mark resolution)

  both modified:   mars.txt

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

The Conflicting Changes

Git detects that the changes made in one copy overlap with those made in the other and stops us from trampling on our previous work. It also marks that conflict in the affected file:

$ cat mars.txt
Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity
<<<<<<< HEAD
I'll be able to get 40 extra minutes of beauty rest
=======
Yeti will appreciate the cold
>>>>>>> 07ebc69c450e8475aee9b14b4383acc99f42af1d

Our change—the one at the HEAD of the main branch—is preceded by <<<<<<<. Git has then inserted ======= as a separator between the conflicting changes and marked the end of our commit from the marsTemp branch with >>>>>>>. (The string of letters and digits after that marker identifies the commit we made in the marsTemp branch.)

It is now up to us to edit this file to remove these markers and reconcile the changes. We can do anything we want: keep the change made in the main branch, keep the change made in the marsTemp branch, write something new to replace both, or get rid of the change entirely.

Let’s keep both of these statements, as they are both valid regarding the Martian environment.

$ nano mars.txt
$ cat mars.txt
Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity
I'll be able to get 40 extra minutes of beauty rest
Yeti will appreciate the cold

To finish merging, we add mars.txt to the changes being made by the merge and then commit:

$ git add mars.txt
$ git status
On branch main
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Changes to be committed:

	modified:   mars.txt

$ git commit -m "Merge changes from marsTemp"
[main 2abf2b1] Merge changes from marsTemp

Git keeps track of what we’ve merged with what, so we don’t have to fix things by hand again.

Let’s make another change to the marsTemp branch:

$ git checkout marsTemp
$ echo "The polar caps will probably be Yeti's home" >> mars.txt
$ git add mars.txt
$ git commit -m "A note about Yeti's home"
[main 34avo82] A note about Yeti's home
 1 file changed, 1 insertion(+)

And merge that change into main branch

$ git checkout main
$ git merge marsTemp
Updating 12687f6..x792csa1
Fast-forward
 mars.txt | 1 +
 1 file changed, 1 insertions(+), 0 deletions(-)

There is no conflict and our changes are added automatically

Still seeing a conflict?

This exercise is dependent on how the merge conflict was resolved in our first merge of the marsTemp branch and may still result in a conflict when merging additional commits from the marsTemp branch.

$ cat mars.txt
Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity
I'll be able to get 40 extra minutes of beauty rest
Yeti will appreciate the cold
The polar caps will probably be Yeti's home

We don’t need to merge again because Git knows someone has already done that.

Git’s ability to resolve conflicts is very useful, but conflict resolution costs time and effort, and can introduce errors if conflicts are not resolved correctly. If you find yourself resolving a lot of conflicts in a project, consider these technical approaches to reducing them:

Conflicts can also be minimized with project management strategies:

Create a conflict between branches and resolve it

  • Create a new branch off of the main branch
  • Make a change to a file in the main branch
  • Change to the new branch
  • Make a change to the same line in the same file
  • Change back to the main branch
  • Merge the new branch into the main branch
  • Address the resulting conflict in the text editor of your choice
  • Add the file containing the conflict and commit conflict resolution to the repository

Solution

# to make sure we're starting in the main branch
$ git checkout main 
# create a new branch, but don't change into it
$ git branch new_branch 
# make a change to the file
$ nano mars.txt 
# add changes in mars.txt to the staging area
$ git add mars.txt 
$ git commit -m "Small change to mars.txt"
# switch to the new branch
$ git checkout new_branch 
# make a change to mars.txt on the same line
$ nano mars.txt 
# add changes in mars.txt to the staging area
$ git add mars.txt 
$ git commit -m "Another change to mars.txt"
# change back to the main branch
$ git checkout main 
# attempt to merge the branches
$ git merge new_branch 
# address conflicts by removing `<<<`, `===`, and `>>>` lines leaving the desired changes intact
$ nano mars.txt
$ git add mars.txt
$ git commit -m "Resolving conflict in mars.txt."

Key Points

  • Conflicts occur when files are changed in the same place in two commits that are being merged.

  • The version control system does not allow one to overwrite changes blindly during a merge, but highlights conflicts so that they can be resolved.