December 2013

Gavin Pickin

Git for Dummies - Merge Conflicts - Resolving Diff Files

Source Control

Welcome back to another post in our Git for Dummies series. We have covered a lot of things, too many to keep posting in the introduction, so click on the Source Control Category on the right hand side to see all of the posts... from Installing, Setting up SSH keys, BitBucket, Remote Repos... but today, we're going to talk about what happens when it doesn't all go to plan. 

One of the great benefits of Git, is that is it distributed, and you can have repos here, there and everywhere. You have several developers working on your project, and they are all working on different files, mostly, sometimes, you might edit the same file. Oh no, are we going to lose someones changes? No, not at all, and most of the time, Git is smart enough to recursively merge the files automatically for you. Of course, you knew there was a but coming... sometimes, if you change the file in such a way Git cannot tell what change should be used... for example, you both edit the same line / chunk of code... then Git says, I'm not messing with this, you fix it, and creates a Diff File (as I like to call it). 

What do we do now?

To see what Git actually does, I'll reproduce this, very quickly here.
I decided to make a new Git Repo called Git101 to play with.
I also make two directories on my machine, git1 and git2. These two repos have the remote repo setup.

$ mkdir gitplayground
$ cd gitplayground/
$ mkdir git1
$ mkdir git2
$ cd git1
$ git init
$ git remote add origin ssh://
$ cd ../git2
$ git init
$ git remote add origin ssh://

Ok... now we want to make a file, readme.txt. Everyone updates the readme all the time, so its going to have conflicts, of course... so lets make the readme in git1. Then we'll commit, then push it to the remote. For now, we'll just add the following text to the file "This is our first commit"

$ nano readme.txt
$ cat readme.txt
This is our first commit
$ git add readme.txt 
$ git commit -m "Created readme"
[master (root-commit) 1106623] Created readme
 1 file changed, 1 insertion(+)
 create mode 100644 readme.txt
$ git push -u origin --all

Now, from git2, we want to pull the readme from the remote repo, and we'll make some changes, and push the changes back to the remote when we're done.

$ cd ../git2
$ git pull
$ nano readme.txt 
$ cat readme.txt
This is our first commit - this is out second commit
$ git add .
$ git commit -m "Updated readme.txt"
[master 028f298] Updated readme.txt
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git push origin master

While our speedy dev was working on git2, our dev on git1 was also busy, updating the readme.txt file. They update the first line as well... but their file was worked on before git2's change was made, so this is what it looks like here.

$ cat readme.txt
This is our first commit
$ nano readme.txt
$ cat readme.txt
This is our first commit - this is our third commit but on different repos
$ git add .
$ git commit -m "3rd commit to readme.txt - git1 repo"
[master 8ce958a] 3rd commit to readme.txt - git1 repo
 1 file changed, 1 insertion(+), 1 deletion(-)

Ok, now I'm ready to push my changes... but before I do, I pull down new changes, and ta-da, we have the conflict.

$ git pull origin master
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From ssh://
 * branch            master     -> FETCH_HEAD
   dc1eed4..028f298  master     -> origin/master
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.

Ok, so that took me longer than I thought to set it up, but the short of it is, 2 devs, working on the same file, and when trying to merge the changes, Git cannot automatically merge, and so it created a diff file... and that looks like this.

cat readme.txt
<<<<<<< HEAD
This is our first commit - this is our third commit but on different repos
This is our first commit - this is our second commit
>>>>>>> 028f2988c1f977105b311b10e59706125756f9ec

Ok... so the file has essentially both of the conflicting lines in the file now. First, it shows the head, with the <<<<<<  and then after the ====== it has the second version. How do we fix this? Basically, merge the conflict how you see fit. If you try to ignore it, git will tell you sorry, you have to fix it... so lets just make the changes. In this case, we'll make it say them all in order. So lets do that. 

$ nano readme.txt 
$ cat readme.txt 
This is our first commit - this is our second commit - this is our third commit but on different repos

Now, lets see what the files look like... we'll do a Git status.

$ git status
# On branch master
# You have unmerged paths.
#   (fix conflicts and run "git commit")
# Unmerged paths:
#   (use "git add <file>..." to mark resolution)
#	both modified:      readme.txt
no changes added to commit (use "git add" and/or "git commit -a")

So now we have modified the file, and it shows both modified, to know it was modified in both locations. To resolve the conflict, we add the file again, and then commit... and push to Origin Master

$ git add readme.txt 
$ git commit -m "Fixed Merge Issue"
[master b64b6da] Fixed Merge Issue
$ git push origin master
Counting objects: 10, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 692 bytes | 0 bytes/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To ssh://
   028f298..b64b6da  master -> master

Now, all we have to do it pull the new merged file into our other local repo. git pull origin master and we're done.

Its a pretty long post, with all the inputs and output, and you might be thinking, wow this is a lot of work. Consider this, how much work would it be to lose a whole change or series of changes? How much work would it be to go through and compare files? Its a lot, I used to do it all the time, I know even recently we have had people overwrite code because something wasn't in a repo... its only a lot of work to fix the conflict, if you didn't do it, you'd have a lot more work to worry about.

I think its a great tool, and this is very cool.

A word to the wise, like I mentioned in another post... always pull down and merge on dev / staging servers. If you get a conflict on the production side... it will create a diff file, in production, and that does not work out too well, its bad enough if its staging... but production, you might get shot for doing that.

Thanks for reading, hopefully this helps, check back soon, for more Git for Dummies (and a lot of other things)


PS: I found this other post interesting when I was learning (still am admittedly), showing GUI and more in depth tools and commands, if you want to dive a lot deeper. I'm trying to keep my simple (as can be with a Professional tool)... but if you want to dive deeper, their whole site is a pretty good resource.
The Git Guys -

Blog Search