At the turn of the century, I was lucky to involved in several projects that developed the practice of Continuous Integration. I wrote up our lessons from this work in article on my website, where it continues to be a oft-referenced resource for this important practice. Late last year a colleague contacted me to say that the article, now nearly twenty years old, was still useful, but was showing its age. He sent me some suggested revisions, and I used this as a trigger to do a thorough revision of the article, considering every section in the original, and adding new ones to deal with issues that have appeared in the last two decades.
During those decades Feature Branching has been widely adopted in the industry. Many colleagues of mine feel that Continuous Integration is a better fit for many teams, I hope this article will help readers assess if this is the case, and if so, how to implement Continuous Integration effectively.
Still have the first edition of his book on my bookshelf. Wrote code and product managed on two different CI systems (Bamboo and Jenkins). Still cool to see CI evolving!
I feel like CI to master with pull/merge requests in very short lived feature branches works really well, even better than when everyone tried to merge their in progress work to master. Though, both are certainly better than when you’d work on a release branch for 3 months, try to keep it in sync with master and a few hotfix branches, and then merge it all at once at the end. That was a total nightmare, and was actually really common.
I fully endorse your first option, how I used to work. In my latest team, all PRs go through an overworked "code owner" so end up backing up and getting out of date. Breakages in PRs from merging latest master get sent back to me to "fix", ie extra work only required because current master is so behind the curve.
We also work with feature branches and I try to understand which signs will tell if we have to much integration problems because of the feature branches. Right now we really focus on closing pull requests as fast as possible, but still use feature branches that live for a few weeks. I think the maximum lifetime of a feature branch in our project is 5 weeks.
You mentioned very short lived feature branches. What does that mean in your case? A few days or weeks?
I do anything from 10 minutes to months depending on the scope. Yes it’s painful to have longer lived branches but when you make a months long branch it’s because the pain of doing it any other way would be greater. Most often the longer lived branches are high cost/risk/reward experiments that may or may not turn out successful. E.g swapping out some component that can’t be done side by side easily (as an example from the real world would be moving from .NET framework to .NET core in a several hundred man-year code base). Most “short” branches I do is 24-48h so typically a half day to a full day of coding then about the same amount of time waiting for reviews and validations.
How long the branches live isn’t the most relevant factor when considering integration problems. How often do you integrate? If you aren’t merging the branch yet, do you at least rebase it daily? If so, you aren’t going to run into integration problems.
If you go off on your own and then try to integrate after more than a month of development, then yeah, of course you are going to have diverging work that results in integration problems. That’s why continuous integration explicitly says you should be integrating at least daily. Otherwise it’s not continuous.
Of course, you might cause other people problems by dumping more than a month of work in your master branch all at once. That’s why things are easier with short-lived branches. But if you want to avoid integration problems yourself, integrate continuously.
I never felt the need/use for reintegrating release branches. I just fork those off so that new developments with more unstable code can continue in the mainline. Any hotfixes in the release branch then must be applied both to the release branch and the mainline, but I don’t think that’s a drawback. Usually it’s a workaround in the release branch but a more thorough refactoring in the mainline to solve the issue long term.
As an added bonus you can have multiple release branches for 1.0 and 2.0 at the same time, or even forked release branches where 1.1 is forked from 1.0 if necessary.
You have multiple major release branches, multiple dot release branches related to each of these, and hot fix branches for any live ones and you aren’t running into merge issues? I agree it’s easy to make lots of forks but at some point changes you made in the last hotfix for a 1.1 release has to find its way to 2.3 right?
A worthwhile distinction might be the kind of applications under these branching strategies; web apps typically only have one live version which avoids the problems you've mentioned.
If you only have one live version then I’m even more confused why you’d need all these different major and minor version numbers and their hotfixes to be in simultaneous development.
CI does not seem to provide a convincing solution for reviews (in the text mainly mentioned as problem when not applying CI, and for CI only covered as an FAQ entry).
With everyone pushing their changes to main (even if tested...) before getting main to a releasable state there's the open items of reviews (every commit/push), fixes, re-review, ... That might work with developers writing flawless code or relaxed reviews, but for me it was painful in reality.
CI shifts the problem from having to solve merge issues before release to having to solve review issues before release. Releasing is impossible if merges fail, but reviews can be skipped. CI seems to promote reduced review quality.
A perfect solution would avoid all problems close to the release.
In addition to small/fast feature branches an automated temporary what-if branch with frequent merges can provide a preview to detect and solve issues early, while avoiding troubles in main. It seems to help with the main issue CI solves (avoiding conflicts detected late), without causing degraded review quality.
What worked for us was actually rebasing, and having one person orchestrating the merges. That way you can have 10+ feature branches and only when you are ready to merge you rebase and check everything is working fine.
20 comments
[ 4.5 ms ] story [ 72.7 ms ] threadA major revision of Continuous Integration
At the turn of the century, I was lucky to involved in several projects that developed the practice of Continuous Integration. I wrote up our lessons from this work in article on my website, where it continues to be a oft-referenced resource for this important practice. Late last year a colleague contacted me to say that the article, now nearly twenty years old, was still useful, but was showing its age. He sent me some suggested revisions, and I used this as a trigger to do a thorough revision of the article, considering every section in the original, and adding new ones to deal with issues that have appeared in the last two decades.
During those decades Feature Branching has been widely adopted in the industry. Many colleagues of mine feel that Continuous Integration is a better fit for many teams, I hope this article will help readers assess if this is the case, and if so, how to implement Continuous Integration effectively.
You mentioned very short lived feature branches. What does that mean in your case? A few days or weeks?
If you go off on your own and then try to integrate after more than a month of development, then yeah, of course you are going to have diverging work that results in integration problems. That’s why continuous integration explicitly says you should be integrating at least daily. Otherwise it’s not continuous.
Of course, you might cause other people problems by dumping more than a month of work in your master branch all at once. That’s why things are easier with short-lived branches. But if you want to avoid integration problems yourself, integrate continuously.
As an added bonus you can have multiple release branches for 1.0 and 2.0 at the same time, or even forked release branches where 1.1 is forked from 1.0 if necessary.
With everyone pushing their changes to main (even if tested...) before getting main to a releasable state there's the open items of reviews (every commit/push), fixes, re-review, ... That might work with developers writing flawless code or relaxed reviews, but for me it was painful in reality.
CI shifts the problem from having to solve merge issues before release to having to solve review issues before release. Releasing is impossible if merges fail, but reviews can be skipped. CI seems to promote reduced review quality.
A perfect solution would avoid all problems close to the release.
In addition to small/fast feature branches an automated temporary what-if branch with frequent merges can provide a preview to detect and solve issues early, while avoiding troubles in main. It seems to help with the main issue CI solves (avoiding conflicts detected late), without causing degraded review quality.
see https://martinfowler.com/recent-changes.html