Branching with git
a basic introduction
If you're using git
for source control and haven't started making use of branching yet – this will hopefully give you the nudge that you need.
What is branching?
Imagine that you're working on a feature for a project. You're half way through when somebody asks you to fix an urgent problem on a file you've already made changes to. At this point you have three options;
- Revert the file, make the change, commit it, then redo your original work.
- Clone another copy of the repo, and make the change in there.
- Hold off on the urgent fix until your current feature is completed.
None of these are ideal. 1) Can get complicated very quickly, and without advance notice. 2) May not be straight forward, and potentially requires a second copy of your environment (database etc.). 3) If it really is urgent, waiting might not even be an option.
Branching allows you to create multiple streams within your git repository. A common use case is to keep each feature you are working on isolated within its own branch, so that you can easily keep track of related changes.
In fact, if you have been using git
you're already using a branch. By default, the first branch git creates for you is called master
. In larger projects, the general rule is that master
is the current live software.
There are a variety of strategies on branching and workflows, but this guide will focus on introducing the very basics. I've included some further reading at the end.
Creating a branch
Let's quickly create a new git repo to have a play with;
> mkdir ~/branching_test
> cd ~/branching_test
> git init
> touch README.markdown
> git add README.markdown
> git commit -m "initial commit"
If that's worked, you should now have a basic git repository with a blank readme file.
Now let's put some basic text into that readme file, and submit that.
> echo "This is the first README change" >> README.markdown
> git add README.markdown
> git commit -m "updated readme"
Right now, our git repo looks something like the following;
C0 > C1 (master)
OK, so let's pretend we've been asked to update the readme to include the names of the author. No problem, let's create a new branch to do this on.
> git branch add-author-names
Note that there cannot be any spaces in the branch name and the convention is to use hyphens between words.
You can type git branch
at any point to see the current branches, with \*
denoting the current branch. If we run that now, we can see that master
is still our current branch even though we just created a new one.
> git branch
add-author-names
* master
This means any changes we make will be on the master branch, so let's switch using;
> git checkout add-author-names
> git branch
* add-author-names
master
So let's add an author to the readme;
> echo "Author: Homer J Simpson" >> README.markdown
> cat README.markdown
This is the first README change
Author: Homer J Simpson
> git add README.markdown
> git commit -m "add author to readme"
Now we've added the author on that branch, internally git now looks like this;
C2 (add-author-names)
/
C0 > C1 (master)
In fact, if we checkout the master branch and look at the readme file, our author isn't included.
> cat README.markdown
This is the first README change
Author: Homer J Simpson
> git checkout master
> cat README.markdown
This is the first README change
OK. So even though we now know it is a bad thing to work on the master branch directly, let's do it anyway so you can see what happens when we're working on two things at once.
> git checkout master
> echo "Description: This is the README file" >> README.markdown
> cat README.markdown
This is the first README change
Description: This is the README file"
> git add README.markdown
> git commit -m "added a description to the file"
So now our repo looks something like;
C2 (add-author-names)
/
C0 > C1 > C3 (master)
Merging
After we've completed our change to add the author names, and normally once we've had it tested, we want to add it back into the master branch.
We actually want to make our commits look more like this;
C0 > C1 > C2 > C3 (master)
To do this we perform something called a merge. First we need to checkout the branch we're merging into, in this case master. Then run the merge command.
> git checkout master
> git merge add-author-names
Auto-merging README.markdown
CONFLICT (content): Merge conflict in README.markdown
Automatic merge failed; fix conflicts and then commit the result.
RUH ROH!
Git has detected that we've modified the same file in both branches, so it's paused the merge process to give you a chance to fix the file manually. If you take a quick look at that file you can see that git has put in some handy pointers to what has changed.
> cat README.markdown
This is the first README change
<<<<<<< HEAD
Description: This is the README file
=======
Author: Homer J Simpson
>>>>>>> add-author-names
You can either fix this manually, or through a visual tool. You can even configure git to launch this tool for you when you use git mergetool
. Once you're finished the file should look like the following;
> cat README.markdown
This is the first README change
Description: This is the README file
Author: Homer J Simpson
Once this is done you can take a look at git with git status
. If it hasn't been staged automatically by your merge tool (or you fixed it by hand) then you should run git add README.markdown
. You may also have a README.markdown.orig
hanging around, which you can get rid of with rm README.markdown.orig
.
Make sure you commit the merge, with a useful commit message
> git commit -m "Merged in add-author-names feature"
You've now completed a basic branch and merge. For this simple example I'm sure it seems like overkill, but you will quickly find it useful when working on larger features – especially when working on overlapping files. This is really just scratching the surface though, and I really recommend you do some further reading on the subject... I've included a few links I found useful.
Further reading
http://git-scm.com/book/en/Git-Branching-Basic-Branching-and-Merging
http://nvie.com/posts/a-successful-git-branching-model/