note, this post was sitting in drafts for a few years ago and suddenly has become top of mind again
in my post about git branching problems, I neglected to inform/expand on the "real" problem.
Namely, Delaying integration is bad(tm)
The History
Waaaay back in the olden days, when folks used tools like
RCS,
cvs, and
svn...branching was...well downright difficult. Or rather, reintegrating the branches and/or cherry picking single commits without making things super complicated was very difficult. In those days, many folks adopted "trunk based development"...which meant...everybody worked on the trunk, and if you had conflicting changed you had to deal with it...RIGHT NOW. Moreover it made things like long running divergent branches a wicked problem when trying to bring back into the mainline...so most people just "didn't do it".
Then Linus Torvalds Changed Things
Well, in fairness, distributed VCS tools had been around a while, but he sorta made "sharing divergent ideas and development paths" easier, or at least more cost effective. This was great for the linux kernel team and many folks relatively quickly adopted his new version control tool named
git. git is a great tool, don't get me wrong, but I feel many of the problems it solved are not necessarily problems that a well run/organized software delivery organization has.
Gitflow Killed Git For Me
Some time back in the early 2010's,
Vincent Driessen came up with
gitflow which, to me...in a very specific context...made a lot of sense. However, I feel he and his post have had the value of the concept victimized by the effectiveness of it getting mindshare without context. At the end of the day, for web applications and continuous delivery models...gitflow is "very often harmful" (Vincent actually added an addendum to that effect a few years ago). For packaged software running for different clients with different featuresets/chipsets/architectures...I could be convinced of it's value (as I can imagine it, but I don't work in that kinda space so I don't have real experience to draw from).
But Back to My Point
At the end of the day, maintaining multiple codebases is HARD...sorry I mean
REALLY HARD and not a problem you want to take on if you don't have to. For folks trying to do continuous delivery of software as a service or other api addressible solutions (think MACH architectures as an example), why would you even think about doing this? "maybe" I could imagine a team that has client specific SaaS solutions that they want to maintain "kinda" parity with, but other than that, most of the clients I work with are actually hampered by trying to solve a problem they don't have by overcomplicating thier branching strategy.
"There is only the next release"
I say this, because that's generally what a branch should represent...which is to say "only the mainline matters". If you're branching every feature, every project, every release, every hotfix...you're creating a maintenance and discoverability absolute nightmare. If there is incomplete work that shouldn't be released, you have a "software design problem", not a "branching strategy problem", and you should seriously start to consider "how can I design this new feature so that the code can go into the next release...even if it's not 100% complete...without breaking existing functionality.
Why I bring up feature switching
One approach to solving the previously mentioned problem is to include feature switches. This enables you to (at runtime ideally) switch new or existing functionality on or off based on an external configuration. This means if "add to cart and get reminder email if the cart isn't checked out in 20 minutes" feature isn't ready for production at the next release off the mainline...you need to design up front for a switch that says "enableReminderAfter20Minutes" that by default is "off" and can be switched "On" in any environment at any time. Not only does this help fix the branching problem, but it also fixes the "proliferation of environments" problem that happens when you start arguing about "but the branch with the reminder needs to be in QA tomorrow" and the "branch without it needs to be in QA for 1 hour" to verify a potential problem in production. Instead of spinning up two environments, you just switch the feature off for 1 hour, verify what you need to verify, then switch it back on. Of course, you can always have another environment set up for long running breakfix activities or other things of that nature...but the environments all run the same code, just with different configurations. Put another way, eject these problems from the source code control context and into the environment/configuration management context.
For further reading, I would suggest
Gitflow considered harmful as well as
Feature Toggles.
Comments