However the problem in our case was that CMS is only a part of our enterprise solution and we cannot afford to stop developing new features - most of the team were still actively adding new features to the same codebase.

In order to avoid merging horror I decided to try to stay in trunk for as long as I can and to postpone branching to the very last moment.

My idea was to utilize precompiler directives and conditionally compile different annotations for different CMS versions.

I had a vision to write a tool that automatically browses through our codebase and transpiles page type builder definitions into those kind of conditional definitions. I decided to implement it using Roslyn and its powerful implementation of the visitor pattern. However I found it quite time consuming (I will share some more details in a future post).

Unfortunately this approach generates a lot of noise; regex does not support conditionals so it's not possible to say: 'IF namedGroup[ExcludePageTypes] is not null then ...'. You can simply provide only 1 replacement string.