When you have several teams working in tandem on a large project, it can be frustratingly easy to break the build by checking in some code that works for you, but ends up breaking someone else's code. It requires a high level of concentration to ensure that the code you check in works with the latest changes from everyone else, especially when each team is responsible for different parts of the code base. Sure, in an ideal world the separation of concerns should help safe-guard against this, but that doesn't mean we can't use other means to help enforce a stable mainline.
Over the last few weeks, I've been looking into different strategies and how to apply them to the dev team at my job, as we are trying to streamlining our development process for future projects. I am by no means an expert on the subject of source control or branching, which is why I've written this post as a mental exercise to try and put into words the ideas I've tossed back and forth.
Branching by Team (Purpose)
Say, for instance, that we have a mainline branch, which should at all times be our stable branch. Then from this, we create n branches, one for each of the n teams. Each team branch allows write-access to the code for the features that team is responsible for, but all other code is read-only to them. When a team has reached a stable milestone on their branch, they merge the code up to the mainline,which then needs to be merged down into each team branch. This could be an ad-hock process, or governed by an iterative agile/scrum-like process.
Merging, Argh...
Assuming that no two teams share write access to any code, then the merge job up to the mainline and down into each team branch should be conflict-free. Oftentimes, this is a fairly unrealistic assumption to make, however, whose alternative requires each merge to be handled with care and by someone with enough bi-team knowledge to resolve the conflicts successfully. Even with only a couple of team branches this can easilly become a difficult and time-consuming process, leading us back to exactly the problem we were trying to avoid in the first place - a fragile mainline.
Keep the Isolation, Loose the Branches
Imagine that, for each team, we set up a 'milestone build' that builds each project owned by that team and drops the compiled assemblies into a shared repository on the mainline. This repository should then at all times contain the latest stable milestone for each team. Then, for each project owned by each team, we remove any references to (read-only) projects owned by other teams and replace them with references to the compiled assemblies located in this shared repository.
Now, instead of branching out each team from the mainline, we can let them work directly on the mainline and instead of having to perform a merge when a stable milestone is reached, they just have to start their milestone build to update the assemblies, which other teams then automatically pick up the next time they perform a 'get latest' from the mainline. We get the exact same isolation between teams as before, without any of the managment overload of having multiple asynchronous branches.
Now, whether the proposed branchless strategy is usable remains to be seen; as of yet it's only an abstract concept that needs to be fleshed out fully and tested out. The simplicity of it is very desireable for us, however, and as we're a fairly small gang of developers where some of us needs to have flexible roles, it can give us the freedom we need while still enforcing a strongly defined process.