I have done source code branching with a ton of teams. The pattern looks pretty much the same independent of what type of branching the team is doing. “We are doing some work that we don’t want other teams to see or get impacted by.” So it goes the team creates a branch to work on a PBI/feature, test some ideas in a Spike or begin the next version of the product. Work sails along swimmingly until the team has to merge the code with mainline (which happens 90% of the time). This is where all hell breaks loose. The team, working in isolation, has created a large amount of code that will no longer integrate with the changes that have happened along the way. At this point code is rewritten (not just refactored), new ideas are brought into the mix, tests are rewritten and so on. For those of you that have been through this, you know what I mean.
Are there ways of dealing this this chaos? Sure!
- Work can minimized with regular forward integrations from the mainline.
- Keep the branch duration short.
- Use Design by Contract techniques coupled with unit and integration tests starting on day 1.
I posted at the beginning of last year that you should always branch with caution. Having given this topic a bit more retrospection, I believe branching to be dysfunctional. Here’s why. We know that as a product moves forward the knowledge about it moves forward as well. As two teams (or more) work in isolation, this knowledge diverges at what appears to be an exponential rate (you can even assume linear and get to the same place). When a branch is merged back to the mainline all the knowledge and assumptions are merged as well. This is where we have a problem. The teams need to “catch up” with each other’s knowledge. From observation, the trick here seems to be to keep the teams collaborating on ALL the code ALL the time. That way, knowledge and assumptions are shared and merge conflicts are eliminated. This is the basis of Continuous Integration (CI). The teams should work together on a single mainline with the code being built and tested in near real-time. Keep the builds fast and consider multi-stage CI or Build Pipeline techniques as the number and type of tests grow.
The question at this point is, “How do I keep unfinished work out of my releases?” There are a couple answers/approaches here. The first is to use Feature Toggles. The concept here is pretty simple, as you begin working on a feature include a config switch that allows you to turn that feature off or make it invisible. Other approaches include the use of authorization to include/exclude features in releases and in modular applications (portals) include/exclude the widget. Along with the ability to turn chunks of code on and off, you will want to make sure you have a comprehensive set of tests and the corresponding automation.
As you begin to walk down this path you will see that you are actually on your way to Continuous Delivery (CD). While a full CD approach is not for everyone, it does offer some really great ideas for keeping you product in a “always shippable” state.