Feature Branching and Continuous Delivery Are Incompatible
When starting up our most recent project, my current project team decided on a set of development practices that included Continuous Delivery and Feature Branching (through Git Flow). There were some members of the team (myself included) that were excited by a true continuous delivery process. Others of the team were similarly excited about using Git Flow.
The first obstacle we reached when we were setting up our continuous delivery pipeline was figuring out which branch to continuously deliver. We changed our minds a few times before settling on a pipeline that would run all the code from the development branch. Except production, that is, which would deploy from master.
This was always a bit confusing and didn't make a whole lot of sense. The idea with git flow is that master always represents production while develop represents the current state of development. The idea of continuous delivery, though, is to reduce the time between what master represents and what develop represents. In the ideal case, develop and master would converge. These worldviews clash quite spectacularly when tried to use in conjunction.
We were able to ignore this uncomfortableness, though, and use git flow for a few more weeks. We found that the overhead of git flow was quite a bit unnecessary. Our team is a well disciplined team that commits several times per day, pushes as often as possible, shares knowledge and code frequently and, despite being on a continous delivery pipeline and committing straight to master, only manages to fail around two builds a week.
Another interesting result was that despite being a reasonably disciplined team, we found that our feature branches would last longer than a couple of days. This was bad because it encouraged "siloing" and discouraged emergent design and refactoring for the whole team. When a pair was working on a story that dealt with the Y Feature area, everyone steered clear of that part of the code until the pair was done and everything was checked in.
In the spirit of Kaizen, the team saw this as a problem and started to improve the process. We decided that feature branches should not last longer than a day and that we should actively pursue getting our branches in as quickly as possible. We pushed this for another week or two before stepping back and looking at the big picture:
- Git flow introduced overhead (and a dirty history log) into our development process. For a team of our size and cohesion, it was definitely on the heavy side of process.
- Our pipeline was somewhat compromised because our promotion scheme from staging to production was to just push a fast forward to master and deploy production. Our pipeline did not directly feed production.
- Git flow encouraged long lived feature branches. With just a bit of attention, we were able to successfully make those long lived feature branches go away. At that point, though, we were creating only local branches and merging them directly to develop.
- We were constantly confused about what was in production versus staging because they deployed from two different branches.
With those in mind, we realized that we needed a "develop on master" strategy. Since moving to that, the team seems to have been quite happy with the approach. The only hiccup is sharing code before it is "deployment ready" -- we have to push a new remote branch to do that. This seems to come up probably once a week and, thus, we feel okay with this solution for now.
If you are interested in learning more about continuous delivery, go get David Farley and Jez Humble's Continuous Delivery. This experience report is just an affirmation of the things that they talk about in the book and the book is a immensely important to anyone trying to implement continuous delivery at their organizations.