Version Control without Source Code
Most software is defined in source code. Not so with Mendix. The most important part of every Mendix project is its model, which contains the domain model definition, forms, and business logic for a Mendix application. This model is interpreted and executed by the Mendix Runtime, resulting in working software.
Version control for developing applications in Mendix is based on Subversion. Subversion has excellent support for text-based diffing and merging, which is used for project resources such as Java actions and theme files. However, since we chose a binary file format for the model file, we cannot use Subversion’s text-based merge algorithm to merge changes between different revisions of the model.
That is why we created our own merge algorithm for the model. The model can be seen as a gigantic tree structure starting with the project as the root node that contains modules, which in turn contain folders and documents. The tree goes all the way down to model elements such as attributes and microflow activities. Therefore, our merge algorithm is tree-based and merges changes between different versions of such trees.
The merge algorithm takes three model trees as its input: the base tree, and two changed trees, called ‘head’ and ‘mine’. This is called a three-way merge algorithm. The first step of the algorithm is to calculate the changes between base and head and those between base and mine. Then it attempts to merge those two lists of changes into one that can be applied to base to yield the merged tree. If it encounters conflicting changes, conflict markers are placed at those locations in the resulting tree. The following image shows an example of a tree merge.
If a document’s contents have changed in both head and mine, then those changes need to be merged. This is done in much the same way as the project structure is merged. Additions, moves, deletes, and edits to both head and mine are detected and attempted to be merged into a single list of changes. If conflicting changes are detected, conflict markers are added.
One advantage of using a tree-based merge algorithm as opposed to a text-based one is this: In text-based merge, when one person moves a block of text while the other modifies it, a conflict will arise. In our tree-based merge algorithm we can merge those changes because we can track a node even though it has been moved. Every node in the model has a unique identifier so that all nodes can be distinguished from each other. If you only have source code, you can not have a unique identifier for text blocks. You could try to use a hash for this, but that changes as soon as the source code changes.
Another advantage is that we have full control of the merge algorithm. We don’t want our users to have to solve a bunch of textual conflicts in the “source code” of their visual models. We present the conflicts visually in a list, allowing users to navigate to the conflicted area in their visual model. The user can use the conflict information in the list to decide how to resolve the merge conflict.