Feature Branching - Taking the ‘Continuous’ Out Of Continuous Integration
Feature branch workflows appear to be the flavour of the month for software development right now. At its simplest, features are developed in isolation on their own branch, then merged back to the trunk. More complicated variants exist, most notably Git Flow.
Git is undoubtedly a powerful versioning tool. It makes branching easy and reliable, and it is truly distributed. These capabilities open up a whole range of possibilities and workflows to support different ways of working. But, as usual, the sharper the tool, the easier it is to cut yourself if you don't understand what you are doing.
My problem is this. Feature branching is a very effective way of working when you have a large, distributed team. Code is not integrated with the rest of the codebase without a lot of checking. Pull requests ensure changes - often done by developers who are in other countries, and often part of a loose-knit open source development team - are reviewed by a core team before being integrated, keeping the main product clean and working. Which is great.
Except it completely undermines the core principle of continuous integration!
Let’s be clear here. If you are not combining every single code change into a single trunk branch at least once every day you are definitely not continuously integrating.
Constant merging of everything as you go is the key enabler for continuous integration. It is the ’secret sauce’ that provides the main benefit of the technique. The clue is in the name. Every1 commit triggers a build and test sequence that checks whether the code has regressed. And the only truly effective way to do that is to keep everyone developing on a single main branch. If something really, really needs a separate branch (the exception, not the rule), then its lifecycle needs to be kept short; ideally, less than 1 day. The longer code stays away from the main branch, unintegrated, the more likely mistakes will go unnoticed.
Having to branch for each feature inevitably means that integration only happens with the rest of the code when the branch is finally merged with the main development branch. Often this is days, even weeks later, and includes many different, separate commits. This is perilously close to the waterfall practice of late integration, and so needs to be avoided unless other factors dictate otherwise - for example, the team is a distributed and loose-knit group of volunteers. If you are working in a small, collocated team, there is absoutely no reason to adopt these regressive patterns.
1 Well, almost every...↩