Thu, 16 Aug 2012

Basic Git Merging

Below is a transcript of me playing around in bash with git branches and merging. I hope this helps to demonstrate the basics of how to create branches, merge them back together, and handle merge conflicts. (All the invocations of subl are just me opening Sublime Text to edit a file.)

smarx-mba:merge smarx$ git init .
Initialized empty Git repository in /Users/smarx/merge/.git/
smarx-mba:merge smarx$ subl todo.txt
smarx-mba:merge smarx$ cat todo.txt
* one
* two
* three
smarx-mba:merge smarx$ git add todo.txt
smarx-mba:merge smarx$ git commit -m "initial commit"
[master (root-commit) e3a0d34] initial commit
 1 files changed, 3 insertions(+), 0 deletions(-)
 create mode 100644 todo.txt

So far, so good! We've created a repository and made our first commit. But here comes smarx...

smarx-mba:merge smarx$ git checkout -B smarx
Switched to a new branch 'smarx'
smarx-mba:merge smarx$ subl todo.txt
smarx-mba:merge smarx$ cat todo.txt
* one
* two - This is a fantastic idea!
* three
* four
smarx-mba:merge smarx$ git add todo.txt
smarx-mba:merge smarx$ git commit -m "praising two, adding four"
[smarx ed0c221] praising two, adding four
 1 files changed, 2 insertions(+), 1 deletions(-)

Smarx came along, created a branch, and made a couple changes. By the way, git checkout -B smarx is just shorthand for git branch smarx && git checkout smarx. While smarx was doing all that, Wade came along...

smarx-mba:merge smarx$ git checkout master
Switched to branch 'master'
smarx-mba:merge smarx$ git checkout -B wade
Switched to a new branch 'wade'
smarx-mba:merge smarx$ subl todo.txt
smarx-mba:merge smarx$ cat todo.txt
* one
* two - This is the worst idea ever.
* three
smarx-mba:merge smarx$ git add todo.txt
smarx-mba:merge smarx$ git commit -m "bashing two"
[wade 6b802a8] bashing two
 1 files changed, 1 insertions(+), 1 deletions(-)

Wade also made a change. Notice that he and Smarx both changed line two. Let's start merging branches back to master...

smarx-mba:merge smarx$ git checkout master
Switched to branch 'master'
smarx-mba:merge smarx$ cat todo.txt
* one
* two
* three

In the master branch, we still have the original version of the file.

smarx-mba:merge smarx$ git merge smarx
Updating e3a0d34..ed0c221
Fast-forward
 todo.txt |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
smarx-mba:merge smarx$ cat todo.txt
* one
* two - This is a fantastic idea!
* three
* four

That "fast-forward" is just telling us that this was a boring merge. The branch smarx was just master plus one commit, so nothing had to actually be merged. We just made master point to the same thing as smarx. (If that didn't make sense to you, take a look at the link at the end of this post for more details about how branches work.)

Okay, that was easy, but now let's try to merge in Wade's changes...

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

Here there's no easy "fast-forward." We had true branching here, and git has to do some work to try to merge the changes. Had Wade and I not both edited the same line, this would have probably gone smoothly, but we made conflicting changes. Let's take a look at the result...

smarx-mba:merge smarx$ cat todo.txt
* one
<<<<<<< HEAD
* two - This is a fantastic idea!
=======
* two - This is the worst idea ever.
>>>>>>> wade
* three
* four

What git has done here is made us a new file that contains both changes. It's up to me to decide which change to take, which I can do by editing the file. Note that the last line ("four") has no merge conflict. That part went smoothly.

Okay, let's edit the file to resolve the merge conflict...

smarx-mba:merge smarx$ subl todo.txt
smarx-mba:merge smarx$ cat todo.txt
* one
* two - This idea is controversial.
* three
* four
smarx-mba:merge smarx$ git add todo.txt
smarx-mba:merge smarx$ git commit -m "resolving conflicting opinions"
[master e457c26] resolving conflicting opinions

Once the file is edited, we just commit it as normal.

You don't have to resolve merge conflicts by hand with a text editor. Git supports calling out to a third-party merge tool to help you resolve merge conflicts. P4Merge is a popular, cross-platform visual merging tool. It would have given me a side-by-side view of my changes and Wade's changes so I could more easily pick which changes to take in the merge.

For those who really want to understand what's going on under the hood when you branch and merge in git, I highly recommend Pro Git section 3.2: Git Branching - Basic Branching and Merging.