Advanced Branching and Merging Strategies: Part I
Branching strategies are crucial to any development operation that wants to remain efficient and effective. This series covers strategies for accomplishing that.
Join the DZone community and get the full member experience.Join For Free
In this two-part 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. 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 and 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, you can revert to a previous model package, revert the latest commits (and lose your work) and generate a new package, or continue development and make a correction to the faulty part. The latter option is 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 piece of 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 the 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 with the main line.
- After a merge to the main line, a merge back to all active branches is needed, as well as 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.
Strategy for Maintenance and Projects
Application of the “no junk in the trunk” principle leads us to strategy number one: a strategy for maintenance and projects in parallel. In this strategy, the following branches can be distinguished:
- the 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, and
- 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 with 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 (one and two). 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 with 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 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.
In the case of a new branch line for maintenance or project, the chosen origin should generally be the latest version of the main line. In the 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, as well as 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 that I can directly see the status of a project folder. Also, Tortoise provides a file viewer that 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 article).
- 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, and
- 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 part two of this series.
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 a consultant in maintenance and support, though intermittently was 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.
This is a guest blog by David de Groot, Mendix Consultant at Sogeti.
Published at DZone with permission of David De Groot, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.