Nevertheless, unfortunately, no matter how much I dig into the topic, I’m not able to convince myself that Martin Fowler’s arguments about Feature Branching, Continuous Integration and Feature Toggling are right.
Please, help me to understand what I’m missing.
Continuous Integration is a weak solution to a wrong problem
I read the last, amazing article by Martin Fowler, OpportunisticRefactoring. It is, as usual, a very inspiring post.
When Martin comes to suggest what not to do in order to achieve a good and proper refactoring, he writes (again) against Feature Branching. Uh? Is Feature Branching something I should avoid if I want to do a proper refactoring? Why, Martin, why?
There’s no Continuous Integration vs Feature Branching dichotomy
Chris Birmele on MSDN Branching and Merging Primer and Jeff Atwood in his famous Coding Horror’s post Software Branching And Parallel Universes described a set of Branching Anti-patterns. I think that this one could describe how I see Martin Fowler when he writes about Feature Branching:
Merge Paranoia: Merging is avoided at all cost, due to a fear of the consequences.
To me, Continuous Integration is a weak solution to a wrong problem. To Martin Fowler, the problem is the branch length: it’s better to merge on the trunk, frequently, in order to minimize merge problems. To me the problem is the version control system you are using: if you are afraid to merge, you should change your versioning tool because VCS are meant to do merges and to help you in your refactoring activities.
Well, I think Martin Fowler could have a fear of merges because he’s using the wrong tool. He likes Subversion and, actually, branching and merging in SVN are a nightmare. Is it the same with modern DVCS, like git?
I completely agree with James McKay and what he wrote in
Why Does Martin Fowler Not Understand Feature Branches
It seems that all the FUD about feature branches boils down to one thing: we should restrict ourselves to trunk-based development because Continuous Integration is the One True Way to do configuration management. But let’s just take a step back and ask ourselves why we do Continuous Integration in the first place? Largely because we were restricted to trunk-only development. If you check in code that breaks the build, then go home, and then someone else checks it out, they can’t get anything done till you return and fix it. You constantly need to have a ready-to-deploy version of your code in case of security vulnerabilities. While this isn’t the whole picture, and there are other arguments in favour of Continuous Integration, it is at least partly a hack to work around the restrictions of trunk-based development.
The vagueness of Martin Fowler’s “cool rule of thumb”—that you should check in “at least once a day” is testimony to this. Cargo culting your way through advice like that will lead to you checking in incomplete, buggy or even downright broken code, and the need for high-maintenance hacks such as feature toggles to compensate.
A hack to work around the limitations of another workaround for the limitations of our tooling.
In another excellent post about this topic, McKay proposes a smart question:
If DVCS had come first, would Continuous Integration ever have been invented?
I’m pretty sure the answer is no.
One of the techniques Martin Fowler proposes as a good alternative to Feature Branching is FeatureToggle: don’t branch; always commit on the trunk; if your feature is buggy or incomplete or not yet planned, disable it with some configuration. Ok, I’m oversimplifying it. Yet I think it’s one of the most weird and weak approach I’ve ever heard. Again, I agree with the arguments of James McKay: believe me, read
Why Does Martin Fowler and Feature Branches Versus Continuous Integration, they are absolutely clarifying. To McKay, Feature Toggling is much much more dangerous than Feature Branching.
The real world
Anyway, I’m still confused: how could Martin be wrong? My doubt grows when I think about Feature Branching in the real world.
Linux is probably one of the biggest software developers community ever.
Linux Torvalds recently posted this comment on his Google+’s page
Merging, merging, merging. The linux-next tree has something like 8600 commits, and I’ve merged about 5600 in the last few days. So more than halfway done. And not everything from linux-next tends to get merged.
Yep. Linux is using Feature Branching. And a single man merged thousands of branches. These are two tiny samples of how Linux Kernel git tree appears:
And know what? No one merges to the trunk. Martin Fowler wrote about DVCS and centralized VCS, but strangely did no mention about the fact that with DVCS developers don’t push their code to the trunk. They have they own repository, and the release manager fetches from them. That’s why DVCS are distributed. It’s not just a matter of speed, as Martin writes.
Linux Kernel developers use Feature Branching. Martin, face it: Feature Branch can work. And it works, actually.
It’s not the practice of feature branching that is the problem but the fact that testing and continuous integration are not decentralized in a lot of organizations. In other words until your changes land on the central branch, you are not doing the due diligence of testing. Even worse, you are not making sure you have tested your changes before you add them to the main branch.
You can’t do decentralized versioning unless you also decentralize your testing and integration. Git has value when used as a SVN replacement. Git has more value when used as a DVCS. There is no good reason why you can’t do decentralized testing and integration with git. Rather the opposite: it has been designed with exactly this in mind. The whole point of git is divide and conquer. Break the changes up: decentralize the testing and integration work and solve the vast majority of problems before change is pushed upstream. If you push your problems along with your changes you are doing it wrong. Decentralized integration is a very clever strategy that is based on the notion that the effort involved with testing and integration scales exponentially rather than linearly with the amount of change. By decentralizing you have many people working on smaller sets of changes that are much easier to deal with: the collaborative effort on testing decreases and when it all comes together you have a much smaller set of problems to deal with.
Again: I agree.
Feature Branching (on a private repository) and merging (with a smart, modern tool like git, not with an old CVS like tool like SVN), to me, means the freedom to create dozen of branches each day, experimenting and feeling safe. I understand that if I would be forced to use SVN or TFS (I am, these days) I would feel the need of some other kind of fan guard (like Continuous Integration).
Hence, I think I’ll try to practice Opportunistic Refactoring and I’ll be heavily using Feature Branching, because I think it can help me refactoring.
What am I missing?