I have become a very passionate user of Distributed Version Control Systems (DVCS) such as git and Mercurial. There are a lot of good tutorials and fan pages that will become classics that explain the differences between Distributed and non-Distributed VCSes. For readers who don’t have a clue what I am talking about: read this introductionDVCSs promote different workflows than centralized systems:

  • Branch when starting to work on a new feature
    • This way the ‘main’ or ‘stable’ branch will not become polluted with experiments.
  • Commit often
    • Because you commit to a feature branch that you are working on. Commits are not messing up anybody else’s code.
  • Merge when needed with what you need
    • When the feature branch has proven itself through testing and reviews, it could be merged into the main branch.

There is a big problem with this approach as Martin Fowler explains in this very insightful article. The merging of your feature branch can cause big issues when others try to merge their feature branches; they suddenly collide with your code.

Fowler suggests two solutions:

  1. Do not use feature branching but instead merge with the stable branch daily. (Continuous Integration)
    • According to Fowler this will keep you up to date with all changes the other developers are making.
    • The stable branch might become less stable. Fowler suggests that a solution might be to change the software’s design so features that are not ready to be deployed yet can be turned off
  2. Merge with others whose work touches the same code.
    • The tricky part is that you don’t always know whose code you might be compromising.

The first alternative feels to me like going back to a centralized VCS which is not bad in itself but you might miss out on keeping a (very) stable branch. As Fowler suggests: a DVCS might be more appropriate for slowly evolving projects while the CI approach fits a rapidly growing system better because it is harder to keep track of all the changes yourself.

The second alternative is something I have been thinking about for a while now from a different angle: cooperation between a developer and a UI/UX designer. Many times they will work on the same feature, their code/design can be very interdependent (e.g. a designer creates the XAML-only View and binds to the ViewModel created by the developer) so merging their work on a ‘feature’ branch might be a very good and valid solution as long as implementing the feature does not take too long or they will be facing a big, evil merge.

NB: I use Mercurial and Bitbucket for personal (one-man or two-man projects). I do not use Visual Studio integration because many times I need to add files to the project that are not in the Visual Studio solution. Also, I am currently setting up a batch file system that will:

  1. Compile the solution
  2. Run the Unit Tests using MSTest
  3. Collect the coverage statistics with OpenCover and ReportGenerator
  4. Collect code statistics with SourceMonitor
  5. Collect potential defects with Gendarme
  6. Commit the files to Mercurial
  7. Push the solution to Bitbucket
  8. Publish the reports on Bitbucket

I am very close to finishing this setup, a couple of bugs in OpenCover and transforming the output of the build, sourcemonitor and Gendarme are keeping me from having this up and running. But that is all fixable, I think.

One thought on “Branching and Merging with Distributed Version Control Systems (git and Mercurial)