Git Topic Branches

I use git for projects I maintain and I try to use it where possible in group projects. I love how I can do work offline, branching is extremely cheap and easy, it's fast and I can make sure that my history is clean. I'd like to write about how I use git so that others can learn from it and that I may also get feedback on how to improve my workflow.

Today I'd like to go over what are known as "feature" or "topic" branches. These are especially useful when you are working with multiple remote repositories, but are also useful for your solo projects. I'll be going over it through an example I hit recently with the two remote repository situation. This usually happens when you have read-only access to the upstream repository and you create your own fork of it so that you have write access to a public repository. Your repository is so that patches you write can be pulled by upstream to merge changes you make into upstream more easily.

For Firmant, I have my own repository that I publish my changes to configured as the cledwyn whereas the official upstream is configured as origin. This is so that Rob may pull from my server and merge my changes from there rather than emailing sets of patches around.

One issue that arises from this is when you push to your repository on master while upstream pushes different code to their master. Since these are public repositories, a force push should not be used, but in this situation, one of the repositories has to be force pushed or merge commits (which I like to avoid when just updating code from a remote repository) would need to be made. Upstream is the worse choice here since it is the official repository. How should one avoid this issue altogether? Since git makes branching easy and fast, this is easy to avoid.

Say that I were to work on the LaTeX feature targeted of Firmant 0.4. If I were to develop on my master branch, I would have to keep rebasing and force-pushing to my repository if I wanted to keep it public somewhere and up-to-date with the latest changes upstream is making without those pesky merge commits. The other possibility is to use a branch to develop the LaTeX functionality. To create this branch, I would issue the following git command:

% git checkout -b dev/latex

This creates a branch named dev/latex and makes it the current HEAD. From here, I can work on the LaTeX code without worrying about clashing branches with upstream. When I am done with the feature (properly documented and tested of course), I can ask Rob to merge my branch into his master.

In order to keep the topic branch up-to-date with master, I merge the master branch into the dev/latex branch:

% git merge --no-ff master # (1)
% # Edit merge conflicts   # (2)
% git add file1 file2      # (3)
% git commit               # (4)

Here's a description of what is happening:

  1. Merge the changes that have occurred upstream into the dev/latex branch. If all goes well, steps 2 and 3 will be taken care of by git. The --no-ff option ensures that a merge commit is made (this is one instance where they are convenient to have, but I'll post about that later).
  2. Fix any merge conflicts.
  3. Add files that conflicted.
  4. Commit the changes.

This keeps my feature branch up-to-date and also allows my master branch to track upstream's master. When I request that Rob merge my commits, I would mention that the dev/latex branch should be merged into master.

Since branches are cheap, I can keep many different topic branches around for various features so that the history for each feature is easily visible and not intermixed with things like commits fixing typos or bugs. This allows a cleaner history to be made so that you can follow the development of a feature instead of having to sift it out from the entire changeset since the feature was started.

In other version control systems, every feature branch would be a complete copy of master which, for large code bases, can become unwieldy and a mess.