Branching in Git is simpler than you might imagine. It’s fast (just 40 characters written to a file), straightforward (one command to create a branch), and efficient (it doesn’t create a complete copy of your current working state). The branches you create don’t need to exist in the remote repository, allowing you to test out new features or bug fixes without disrupting what’s already working. As stated in “Why Git is Better Than X”:
Git allows you to have multiple local branches that can be entirely independent of each other, and the creation, merging, and deletion of those lines of development take seconds. Git makes this process incredibly easy and changes the way most developers work when they learn it.
Despite these benefits, you might still hesitate to use branches due to stigmas associated with previous version control systems. But fret not! We’ll walk through a simple example of branching, merging, and resolving conflicts.
Let’s say I’m working with the Jekyll repository again. I’ll check out a new branch, make some changes in a file, and then merge it back into the master branch:
$ git checkout -b fixes
Switched to a new branch “fixes”
$ vim lib/jekyll/core_ext.rb
$ git commit -am “Adding cutoff method to String”
Created commit 670e353: Adding cutoff method to string
1 file changed, 15 insertions(+), 1 deletion(-)
$ git checkout master
Switched to branch “master”
$ git merge fixes
Updating e53ac7a..670e353
Fast forward
lib/jekyll/core_ext.rb | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
And that’s it! If we want to delete the branch, git branch -d fixes would remove it. Integrating this process into your workflow can be highly beneficial. For instance, Josh Susser has a great post about how he uses branches to work on user stories.
That was a straightforward example of a fast-forward merge, but it’s not always that simple. Let’s go through a scenario where I made changes to the same line of a file in both my master branch and a new branch:
$ vim lib/jekyll/core.rb
$ git commit -am “Causing a merge on purpose”
Created commit 8aba87e: Causing a merge on purpose
1 file changed, 2 insertions(+), 2 deletions(-)
$ git checkout -b conflicts
$ vim lib/jekyll/core.rb
$ git commit -am “Changing cutoff default”
Created commit 6041ddd: Changing cutoff default
1 file changed, 1 insertion(+), 1 deletion(-)
$ git checkout master
Switched to branch “master”
$ git merge conflicts
Auto-merged lib/jekyll/core_ext.rb
CONFLICT (content): Merge conflict in lib/jekyll/core_ext.rb
Automatic merge failed; fix conflicts and then commit the result.
Upon opening the file, Git shows the difference in versions for this portion of text. We need to resolve the conflict by choosing which version to keep:
$ git status
# On branch master
#
# Changed but not updated:
# (use “git add …” to update what will be committed)
#
# unmerged: lib/jekyll/core_ext.rb
#
$ vim lib/jekyll/core.rb
$ git commit -am “Fixing conflict!”
Created commit 9c8e9fd: Fixing conflict!
This creates a special commit with two parent commits from each of the branches that were merged. Future tips will cover using helpers for this process, like git-mergetool and gitk –merge. If you know of good tutorials on these or other methods of merging, feel free to submit a tip! In the meantime, check out Scott Chacon’s GitCast on this topic or the Git Community Book’s guide for more information.