Merging git conflicts

Git merging confused me a lot when I first encountered it so here is my quick guide to merging. Do 'git pull origin master' often to minimise merging problems.

Lets start by creating a Git project base repository:

~/test $ mkdir base
~/test $ cd base
~/test/base $ git init
Initialized empty Git repository in /home/paul/test/base/.git/
~/test/base $ git config --bool core.bare true

Note that the config command ensures that this is not a working copy.

Now we'll create two working copies:

~/test/base $ cd ..
~/test $ git clone base wc1
Initialized empty Git repository in /home/paul/test/wc1/.git/
warning: You appear to have cloned an empty repository.
~/test $ git clone base wc2
Initialized empty Git repository in /home/paul/test/wc2/.git/
warning: You appear to have cloned an empty repository.

Add some files without any problems:

~/test $ echo 'foo initial content' > wc1/foo
~/test $ echo 'bar initial content' > wc2/bar
~/test $ cd wc1
~/test/wc1 $ git add foo; git commit -m 'initial content from wc1'
[master (root-commit) c7ad23c] initial content from wc1
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 foo
~/test/wc1 $ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 237 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /home/paul/test/base
 * [new branch]      master -> master
~/test/wc1 $ cd ../wc2
~/test/wc2 $ git add bar; git commit -m 'initial content from wc2'
[master (root-commit) daf2028] initial content from wc2
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 bar
~/test/wc2 $ git pull origin master
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/paul/test/base
 * branch            master     -> FETCH_HEAD
Merge made by recursive.
 foo |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 foo
~/test/wc2 $ git push origin master
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 515 bytes, done.
Total 5 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (5/5), done.
To /home/paul/test/base
   c7ad23c..2baf473  master -> master

Note that I retrospectively updated wc2 so I could push it without any complaint from git about it being already out of date. I'll forget to update wc1 before I add a new bar file there:

~/test/wc2 $ cd ../wc1
~/test/wc1 $ git status
# On branch master
nothing to commit (working directory clean)
~/test/wc1 $ echo 'another bar from wc1' > bar
~/test/wc1 $ git add bar; git commit -m 'Added bar in wc1'
[master f6c4da5] Added bar in wc1
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 bar

Ok. Now I'm in trouble. I've added a file called bar but its going to be a problem when I attempt to update wc1:

~/test/wc1 $ git pull origin master
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 5 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (5/5), done.
From /home/paul/test/base
 * branch            master     -> FETCH_HEAD
Auto-merging bar
CONFLICT (add/add): Merge conflict in bar
Automatic merge failed; fix conflicts and then commit the result.

OK. git rightly fails to merge bar (it can't tell which file it should use or if/how it should combine the contents). I need to help it out. I have options here. Notice first that we are not in a workable state right now:

~/test/wc1 $ git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
# Unmerged paths:
# (use "git add/rm ..." as appropriate to mark resolution)
#
# both added: bar
#
no changes added to commit (use "git add" and/or "git commit -a")
~/test/wc1 $ cat bar
 2baf4730f14a69a5dee8d671e6de4dc7f1bb1391

I could tell it to accept the wc1 version, I could tell it to accept version already in the base repo, or I could invoke merge and produce a file that is good for both. To decide, its easiest to use the mergetool (make sure you load one of the required tools so it can do its job - I generally use meld):

~/test/wc1 $ git mergetool
merge tool candidates: meld opendiff kdiff3 tkdiff xxdiff tortoisemerge 
gvimdiff diffuse ecmerge p4merge araxis emerge vimdiff
Merging the files: bar

Normal merge conflict for 'bar':
  {local}: created
  {remote}: created
Hit return to start merge resolution tool (meld): meld
# Use visual editor to set the bar file how you want it
~/test/wc1 $ git commit
[master f07da0d] Merge branch 'master' of /home/paul/test/base
~/test/wc1 $ git status
# On branch master
# Your branch is ahead of 'origin/master' by 4 commits.
#
# Untracked files:
# (use "git add ..." to include in what will be committed)
#
# bar.orig
nothing added to commit but untracked files present (use "git add" to track)
~/test/wc1 $ rm bar.orig
~/test/wc1 $ git push origin master
Counting objects: 9, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 626 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
To /home/paul/test/base
   2baf473..f07da0d  master -> master

Note that I tidied up bar.orig which I don't need and that I remembered to push the merge result back to the base repository.


Comments

There are currently no comments

New Comment

required

required (not published)

optional

Australia: 07 3103 2894

International: +61 410 545 357