Diffing and Merging Models is the main purpose of LemonTree. Since models can be highly connected and concurrent editing can lead to conflicts, LemonTree employs some strategies for handling such cases.
Diffing is a two-stage process.
In the first stage, LemonTree examines the models and quickly determines which elements have changed. The result of this step is a list of elements which may have undergone significant changes, but it's not a conclusive one. Put differently, the result of this operation is a strict superset of the changes in the models.
In the second stage, the elements which may have changed will be examined further. LemonTree determines which structural changes happened (Moves, Deletes, Additions), and also examines the internals of elements, basically determining what has changed for each element.
This is also the stage where conflicts will be detected.
Conflicts are detected when changes in both branches are not reconcilable.
Conflict detection is currently done on single elements, meaning their surrounding is not examined - only the elements and their changes themselves are examined.
In the matrix below you'll find the instances where LemonTree currently detects a conflict, and which version LemonTree will prefer.
|Change Type||Unmodified in A||New in A||Modified in A||Moved in A||Removed in A|
|Unmodified in B||No Conflict||Not Possible||No Conflict||No Conflict||No Conflict|
|New in B||Not Possible||No Conflict (1)||Not Possible||Not Possible||Not Possible|
|Modified in B||No Conflict||Not Possible||Conflict:A (2)||No Conflict||Conflict:B|
|Moved in B||No Conflict||Not Possible||No Conflict||Conflict:A (3)||Conflict:B|
|Removed in B||No Conflict||Not Possible||Conflict:A||Conflict:A||No Conflict|
1) In case the new elements are identical in both models, LemonTree doesn't detect a conflict (since Release 2.1.4). "New-New" scenarios with same GUIDs can happen if parts of the model are imported via .xmi.
2) Only a conflict if there is at least one property which is modified in both models.
3) In case the element is moved to the same location in A and B, LemonTree doesn't detect a conflict.
While the diff is symmetrical, the merge is not. When merging, the conflict resolution step favors the 'A' model.
Although LemonTree can be used as a diff tool, there is the option to merge different versions of models. For this, a diff is performed followed by a conflict resolution step. The result of these steps is the Merge Preview which is a model where changes from both branches have been applied.
In case of a conflict in the diffing step, LemonTree still generates a Merge Preview where it employs some merge strategies to make sure that the resulting model is sound.
After this pre-merge step, the applied changes are analyzed further to find out if...
Problems found here will be corrected, and the model will be analyzed again until no such problems are found.
After this phase, the Merge Preview is ready to be written.
When using LemonTree interactively, you have the option to override the changes LemonTree did to the model by using the GUI. Because LemonTree tries to ensure model consistency after every (interactive) step, some actions may yield surprising results. As an example, if you choose to take a (deleted in the other branch) connector by using the UI functionality to do so, this will also take the elements connected by the connector to ensure that the connector is valid. If such an element has been marked as deleted by the merge algorithm, it will change its state and becomes part of the Merge Preview. Depending on the structure of your project, a tiny change such as this can have a huge impact to the model because the owning elements and other dependencies also have to be taken into account.
We will add some means to visualize the impact of such changes. In the meantime, be careful when you are doing manual changes on potentially very well connected models.
Most elements in models can't exist on their own - they have dependencies to other elements which are existential to this element. We call these dependencies Existential Dependencies.
Examples of existential dependencies are
LemonTree adds these elements if they are required to preserve the integrity of the model.
Some elements in Models are pretty complete on their own, but still have some dependencies which are defining characteristics of that element. We call these dependencies Integral Features.
Examples of integral features are
LemonTree respects such integral features. If you select an element to be part of the merge, for example because it was deleted in one branch and you don't want it to be deleted in the merged model, LemonTree also selects the integral features of this element, so that the element is complete. However, if an integral feature has been deleted in one branch, LemonTree respects this and will not resurrect this element, in contrast to existential dependencies where this feature would have to be resurrected in order to get a valid model.