Advanced Branching and Merging Strategies (Part 1 of 2)
In this two-part blog series, I will describe advanced branching and merging strategies for complex operational environments. These strategies are based on my personal experience at current and past clients with multiple projects and ongoing maintenance parallel to each other.
In part one I will give a short description of a basic strategy, as I assume this is what most people use. It is the default strategy for Mendix projects and is directly based on previous Mendix blogs and the documentation on Version Control Concepts. Following that, I will explain one version of advanced strategies for branching and merging that adheres to the “No junk in the trunk” principle. A second strategy will be presented in the next blog.
I make the assumption that readers have a good understanding the basics of branching and merging, Subversion (SVN) and Mendix, as described in the Mendix documentation on Version Control Concepts, which you can find here: https://docs.mendix.com/refguide6/Version+Control+Concepts. However, I will briefly explain how to do branching and merging in the modeler.
Basic Strategy (The Default): Featuring The Main Line
This basic strategy is followed in most Mendix projects as it is the default starting point for every project. This approach is often continued when the project has become larger and is already live. In this strategy, the Main Line is used for almost every type of development: all changes are committed to the Main Line and deployments are only done using the Main Line. Changes are committed one after the other, are usually mixed up, and bug fixes are committed on top of that again. As a result, changes can only be delivered as a ‘package deal’ – take it all or leave it.
Once a version is deployed, the options to correct a bad deployment are limited. For example, 1) reverting to a previous model package, 2) reverting the latest commits (and lose your work) and generate a new package, or 3) continuing development and making a correction to the faulty part. The latter option being the most commonly followed in my experience so far. Note that a rollback of the latest commit(s) is a risky option in itself, after which testing and committing the new model is still needed.
A general well-meant advice: abandon this basic strategy as soon as possible. For example, as soon as a stable version is deployed in one of the testing environments, or at latest when the first release is done to the production environment. Rightfully, of course, you may wonder: what is the alternative? What can be done better? Where is room for improvement?
First and foremost, you should adopt the principle “No junk in the trunk”. Generally, that means:
- ALL development takes place in branches (and NEVER on the Main Line)
- The Main Line is the general starting point for new branches
- Only fully tested changes are merged to the Main Line
- After a merge to the Main Line, a merge-back to all active branches is needed. Also a merge-back to the source branch if development on the branch is continued. This is needed to make sure that all branches stay in sync.
See also “Version Control for Multiple Agile Teams“. For a detailed explanation of the principle and how to apply it, see this website https://www.infoq.com/articles/agile-version-control/.
Strategy for Maintenance and Projects
Application of the “No junk in the trunk” principle leads us to Strategy 1: a strategy for Maintenance and projects in parallel. In this strategy, the following branches can be distinguished:
- Main Line
- A continuous maintenance branch, called, for example, Maintenance or Business As Usual (BAU)
- Optionally a Project branch or feature branch for major changes
- Additionally, there can be hotfix branches for a small production patch
With this strategy, changes are only done on the branches: mainly in the Maintenance and Project branches. Deployment to a test environment is done on a package that is generated from the respective branch. After testing is completed successfully, the changes are merged to the Main Line. After that, the commits have to be merged-back to all the active branches to keep everything synchronized. A production deployment is done from a versioned package from the Main Line, and sometimes done from a tested hotfix-line.
See the illustration below for a visual representation of the main activities of this strategy. With time running from left to right, the three branches are shown as horizontal lines: the Maintenance branch, the Main Line, and a Project branch. Each committed change on a branch is depicted as a circle on that line. Two series of changes were done on the Maintenance branch line and committed (1 and 2). Those changes are initially tested with a deployment package that is generated directly from that line. After any tests are completed and accepted, the changes are merged to the Main Line. In the illustration, the merges are shown as arrows. After the merge, the changes are committed (3) and then merged to the Project branch line (4). Finally, the changes that were committed at number 3 are merged-back to the Maintenance branch line (5) to make sure all lines are synchronized.
How to do branching and merging in the Mendix modeler
To start using branches, a prerequisite for any project is to have the Team Server enabled. The easiest way to do so is to start any project using Team Server. Just do it, it’s for free anyway. Alternatively, this can be done at a later point using the option Upload to Team Server… in the Team menu.
An initial one-time setup has to be done for the Maintenance line. New branches for projects will be needed as projects come and go. Don’t forget to clean up the old project branches. Also, you may need a new branch for feature development or hotfixes. Branches can be created using the menu option Manage branch lines… from the Team menu item. See also the Mendix documentation on Version Control Concepts https://docs.mendix.com/refguide6/Version+Control+Concepts.
In case of a new branch line for Maintenance or Project, the chosen origin should generally be the latest version of the Main Line. In case of a feature or hotfix branch, it depends on what it is for. Such a branch could stand on its own, or be sub-branch of either Maintenance or Projects.
Either way, every branch line will need to deliver their changes and at least the Maintenance and Project. Branch lines will also need to stay in sync, which is where merging comes in. Sometimes, feature branch lines will exist for a longer stretch of time, and you may need to keep them in sync as well. If you don’t synchronize the branch lines, you will run into complicated version conflicts sooner or later.
Merging is done using the Merge changes here… option in the Team menu. Being confronted with three options right away may be intimidating at first. However, just read carefully (actually, you can’t go wrong here as the invalid options will be disabled).
Merging changes from a branch line to the Main Line from the Project or Maintenance branch can often be done using the Port fix or Merge feature branch options. With the Port a fix option, you can still choose to merge one or multiple revisions. The Port feature branch option will not allow that and will merge all revisions that were not previously merged.
Port fix window
Port feature branch window
Using the modeler with one of the branch lines open, you will not have the first two options, which leaves only the Advanced merge option. There, you will have to select the branch line to merge from, and the start and end revision that are to be included in the merge. The selection of revisions is very useful because you don’t necessarily want to include everything in a merge.
Finally, note that all the merges (and all other Subversion actions) can be done in the Tortoise SVN client for Windows. Tortoise SVN also facilitates the reintegration merge or merge-back with a special option. Be aware that not all the versions are compatible with the Mendix SVN setup. Check the Mendix Reference Guide for the correct version if you are interested in using Tortoise.
Personally, I like to do all my branching and merging in the Mendix Modeler. I have Tortoise installed for the icons that are visible in the Windows Explorer so I can directly see the status of a project folder. And also, Tortoise provides a file viewer which can be triggered from the Mendix Modeler where you can compare different (conflicting) versions of Java files, which has been very useful in some occasions.
So what is my experience with the strategy so far? I must say that it works well and that it is a good step forward to being in control of changes and versions. It is a good model, it is simple and delivers what is needed. However, this strategy gives a number of challenges over time:
- Changes for features and fixes can stack up in a development branch line and result in an all-or-nothing package deal (more on that in the next blog)
- Combining branches for deployment in a test environment with changes from both a project and the maintenance branch lines is difficult, and sometimes impossible (when lots of conflicts arise)
To conclude, let’s review the applicability of these strategies and lessons learned in the time that we have been using them. The above strategy is useful in the following situations:
- When you want to separate efforts for maintenance and projects
- For releases with multiple features and fixes that are to be developed separately
- For high risk versus low risk change tracks
The final verdict for the presented strategy is that it’s a good model. It works well in practice and is understandable. We used this strategy successfully for over a year until we ran into serious issues due to its limitations. More on that in the part two of this blog.
Thanks to Richard for planting the seeds and getting me to think about improving branching and merging, and also pushing me to keep improving. Thanks to Reinout, my Sogeti-colleagues Edzo and Louis, and the Mendix reviewers for giving constructive comments. The end-result wouldn’t have been the same without them.
About David de Groot
Now working at Sogeti for three years, David has a been working with Mendix for over 6 years and is a certified Advanced Developer. He has been working at various Dutch and international companies, mainly as consultant in maintenance and support, though intermittently also involved in projects and new builds. David has a background in Oracle and PL/SQL development and holds a Master of Science degree in Artificial Intelligence.
Version Control Concepts in the Mendix Documentation
Version Control with Subversion
- http://svnbook.red-bean.com/ E.g. http://svnbook.red-bean.com/en/1.7/svn.branchmerge.commonpatterns.html
InfoQ Book: Scrum and XP from the Trenches