ConflictsΒΆ

The git merging process can do a good job of identifying how to merge different versions of code together. However, there will be times when git is unable to work out how to merge branches and it will need the code developers to resolve the conflicts.

During the merge process, if a conflict occurs in merging two versions of the same file, git will create a new version of the file showing clearly where the conflict is, complete with the code from both versions. You just need to look at the file and change it to the way you want it. Then you just make a normal commit.

Here is an example of what a conflict looks like when two branches have modified the same line in a file.

First checkout the master branch and add an author and date comment at the head of stats.py. Something like this will do just fine:

# Calculate the sum, average, and standard deviation
# of the values in a text file, formatted as one value per line.
#
# Written by Your Name
# Licensed under the Creative Commons Attribution-ShareAlike license
# https://creativecommons.org/licenses/by-sa/3.0/

Now commit the change:

$ git add stats.py

$ git commit -m "Add license"
[master 59fc796] Add license
 1 files changed, 1 insertions(+), 0 deletions(-)

Now checkout the std_dev branch and make a similar but not identical modification:

# Calculate the sum, average, and standard deviation
# of the values in a text file, formatted as one value per line.
# Edited by Your Name, 8/2/2013.
#
# Author: Your Name <you@example.com>

And commit the change:

$ git add stats.py

$ git commit -m "Add Author"
[std_dev 9bc0d40] Add Author
 1 files changed, 1 insertions(+), 0 deletions(-)

Here is what the node diagram looks like:

_images/node_04_conflict_creation.png

Note

Aliases

Some commands have a bunch of useful options, that can be really powerful when used together. For these commands, you can create short aliases. For example:

$ git config --global alias.lg "log --graph --decorate --oneline"

Creates a permanent alias that gives you a nice, compact log view, when you type git lg. You can still use all the normal options from git log, so git lg --all will show the histories of all branches in a single graph. Try it!

Let’s see what happens when we try to merge the change in the std_dev to the master branch. Remember we have to checkout the master branch first:

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

Here we see that there has been a problem merging the two versions of stats.py. Here is a listing of the version of stats.py that git has put in the working directory:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Calculate the sum, average, and standard deviation
# of the values in a text file, formatted as one value per line.
#
<<<<<<< HEAD
# Written by Your Name
# Licensed under the Creative Commons Attribution-ShareAlike license
# https://creativecommons.org/licenses/by-sa/3.0/
=======
# Author: Your Name <you@example.com>
>>>>>>> std_dev

import sys
import math

values = []
for line in open(sys.argv[1]):
   value = float(line)
   values.append(value)

total = sum(values)

diffSquared = []
for value in values:
    diff = value - average
    diffSquared.append(diff**2)

stdDev = math.sqrt(sum(diffSquared) / (len(values) - 1))

print len(values), 'values were read in'
print 'The sum of the input values is:', total
print 'The average of the input values is:', total / len(values)
print 'The standard deviation of the input values is:', stdDev

The emphasized lines, 4-10 are what you will need to sort out. You don’t necessarily have to choose between the two versions. Edit the file any way you need to resolve the conflict:

# Calculate the sum, average, and standard deviation
# of the values in a text file, formatted as one value per line.
#
# Author: Your Name <you@example.com>
# Licensed under the Creative Commons Attribution-ShareAlike license
# https://creativecommons.org/licenses/by-sa/3.0/

When you are happy with the changes, run git diff. You will now see a diff between three versions, the one in master, the one in std_dev, and the one we just edited in the working directory:

$ git diff
diff --cc stats.py
index 5ee3e25,d45cfa1..0000000
--- a/stats.py
+++ b/stats.py
@@@ -1,6 -1,6 +1,8 @@@
  # Calculate the sum, average, and standard deviation
  # of the values in a text file, formatted as one value per line.
  #
- # Written by Your Name
+ # Author: Your Name <you@example.com>
 +# Licensed under the Creative Commons Attribution-ShareAlike license
 +# https://creativecommons.org/licenses/by-sa/3.0/

  import sys
  import math

If you are still happy, just commit the changes:

$ git add stats.py

$ git commit
[master d7396fb] Merge branch 'std_dev'

You don’t need to add a commit message here, because git has already prepared one for you, but it still gives you the option to edit it.

If you look at the log for the master branch you will see two new commits after the last change you made in this branch: the one for the change you made in std_dev and then the one you just made to resolve the conflict:

$ git log
commit d7396fb47be857136e2e111aeb6d26ddd812956b
Merge: 59fc796 9bc0d40
Author: Your Name <your.name@yourdomain.com>
Date:   Fri Feb 8 22:44:26 2013 +1100

    Merge branch 'std_dev'

commit 9bc0d40b81ea790eed9e849f71b281652dd2bc92
Author: Your Name <your.name@yourdomain.com>
Date:   Fri Feb 8 22:06:32 2013 +1100

    Add Author

commit 59fc7966529113a2f1e6efaef271a490a7df7b5a
Author: Your Name <your.name@yourdomain.com>
Date:   Fri Feb 8 22:02:59 2013 +1100

    Add license

commit 9b7129e86390fcca6a97dc2c8102014e63f5a646
Author: Your Name <your.name@yourdomain.com>
Date:   Fri Feb 8 20:40:56 2013 +1100

    modified stats.py to also calculate and print out the standard deviation

commit 9a202a66e7b2b93b12190dd0b56b594a60ebed22
Author: Your Name <your.name@yourdomain.com>
Date:   Thu Feb 7 11:36:27 2013 +1100

    modified stats.py to output the average as well

commit c6f2746af72c45d6f92741f51b5f4ae1241b79e2
Author: Your Name <your.name@yourdomain.com>
Date:   Tue Feb 5 16:36:40 2013 +1100

    put .gitignore under version control

commit aaad9ced7a33f5f8dc301411c2958f0267cfd82c
Author: Your Name <your.name@yourdomain.com>
Date:   Tue Feb 5 16:35:40 2013 +1100

    Initial commit of stats.py

Note, that no further commits have been made to the std_dev branch, it is still the way it was before the merge:

$ git log std_dev
commit 9bc0d40b81ea790eed9e849f71b281652dd2bc92
Author: Your Name <your.name@yourdomain.com>
Date:   Fri Feb 8 22:06:32 2013 +1100

    Add Author

commit 9b7129e86390fcca6a97dc2c8102014e63f5a646
Author: Your Name <your.name@yourdomain.com>
Date:   Fri Feb 8 20:40:56 2013 +1100

    modified stats.py to also calculate and print out the standard deviation

commit 9a202a66e7b2b93b12190dd0b56b594a60ebed22
Author: Your Name <your.name@yourdomain.com>
Date:   Thu Feb 7 11:36:27 2013 +1100

    modified stats.py to output the average as well

commit c6f2746af72c45d6f92741f51b5f4ae1241b79e2
Author: Your Name <your.name@yourdomain.com>
Date:   Tue Feb 5 16:36:40 2013 +1100

    put .gitignore under version control

commit aaad9ced7a33f5f8dc301411c2958f0267cfd82c
Author: Your Name <your.name@yourdomain.com>
Date:   Tue Feb 5 16:35:40 2013 +1100

    Initial commit of stats.py

And with your new alias:

$ git lg --all

*   d7396fb (HEAD, master) Merge branch 'std_dev'
|\
| * 9bc0d40 (std_dev) Add Author
* | 59fc796 Add license
|/
* 9b7129e (tag: sum_average_stddev) modified stats.py to also calculate and print out the standard deviation
* 9a202a6 (tag: sum_and_average) Add average
* c6f2746 Add gitignore
* aaad9ce (tag: sum) Add stats.py

Here is the state of the node diagram after this merge:

_images/node_05_conflict_resolve.png