Large models are many a times split into smaller files to make them easier to work on. This helps developers to work on different parts of the model simultaneously, without getting in each other's way.
In an ideal scenario, each part of the model should be in its own file. This way, developers can work on specific features without affecting other parts. This boosts parallel development, meaning many people can work on the model at once, minimizing the delay in the process.
Often, different features might need to change the same part of the model. In such cases, developers may need to merge their changes, and that's where the Merge tool in Model RealTime comes in.
Model RealTime allows a model to be split into model files (.emx) and fragment files (.efx). Fragment files are used when a containment hierarchy has to be split on multiple files. The model file then contains the root element in the containment hierarchy, typically a package. Elements that are contained in the root element, for example classes, can be stored in separate fragment files. This continues recursively so that elements that are roots of fragment files may in turn contain other elements that are stored in separate fragment files. A set of files that stores a model element and its (directly or indirectly) contained elements is called a logical model. The snapshot below illustrates this concept:
The file "HelloWorld.emx" stores the root package. It also stores some elements that are contained by this package such as the class "Class1" and the capsule "HelloWorld". However, the class "FragmentClass" is also owned by the "HelloWorld" package but is stored in its own fragment file "FragmentClass.efx". Looking inside the class "FragmentClass" we see that its attribute "status" also is stored in "FragmentClass.efx" while the nested class "InnerClass" is stored as the root of another fragment file "InnerClass.efx". In this example the logical model consists of the three files "HelloWorld.emx", "FragmentClass.efx" and "InnerClass.efx". In general, a logical model in Model RealTime consists of exactly one model file (.emx) and zero to many fragment files (.efx).
The Model RealTime Merge tool understands the concept of a logical model, and can expand the request to merge a single file, so that the entire logical model to which the file belongs gets loaded in the merge session. Thereby the Merge tool can merge all files in the logical model in one single merge session, called a logical model merge session. In the same way a logical model compare session is a single compare session where multiple files (all belonging to the same logical model) are compared. Below we primarily talk about logical models in the context of merge, but keep in mind that the logical model concept also applies when comparing models.
Logical model merge has some key benefits compared to file-by-file merge. First of all it leads to fewer merge sessions for a model that is stored in multiple files. For example, consider a model that consists of these six files:
Model1.emx
Fragment1a.efx
Fragment1b.efx
Model2.emx
Fragment2a.efx
Fragment2b.efx
If all these six files have been modified, it would require six individual file-by-file merge sessions to merge the entire model. With logical model merge only two merge sessions are required; one for the logical model consisting of the first three files (rooted at Model1.emx), and another for the logical model consisting of the other three files (rooted at Model2.emx).
Another benefit comes from the fact that logical model merge has a bigger scope for analyzing the changes between the merged models. For example, if you would move an element from one fragment file to another fragment file within the same logical model, a logical model merge session will present that change correctly as a Move change, while with file-by-file merge you would get a Delete change when merging one of the fragment files, and an Add change when merging the other fragment file.
The most important benefit, however, is that logical model merge is better at protecting the integrity of a logical model. If you perform refactoring operations which affect the structure of a logical model (i.e. how the model is structured in model and fragment files) this leads to changes that can be really tricky to merge correctly using file-by-file merges. With logical model merge you avoid the risk for model corruption after the merge.
There is a preference General - Compare/Patch - Modeling Compare/Merge - Logical Model Settings - Disable Logical Model Synchronization which can be set in order to turn off the support for logical model compare/merge in Model RealTime. However, it is not recommended to set this preference if your model contains logical models that consist of more than one file. If you do set this preference, you should be careful not to modify the logical model structure on parallel development streams, since the Merge tool then will not be able to correctly merge such modifications. You should also avoid refactoring, which spans across different files in the logical model, such as moving an attribute from a class stored in one fragment file, to a class stored in another fragment file.
The preference Enable Sparse Logical Model Merge can be set if you find that your merge sessions consume too much memory and/or takes too much time to start. As explained in the note for this preference, a logical model merge implies that four, potentially quite big, models are loaded into memory during the merge session. With sparse logical model merge enabled the Merge tool will optimize this to avoid loading those fragment files that have not been modified. However, although this both speeds up the launch of the merge session, and makes it consume less memory, it is only recommended to set this preference if this is a concern for you, due to the side-effects that are mentioned in the note.
Note that not all Model RealTime integrations with CM systems support logical models, and those that do support them can do so to various degrees. Specific CM integrations can therefore have additional or different preferences related to logical model support which control the behavior in more detail. For example, the EGit integration has specific preferences in the Team – RSx EGit Integration preference page for enabling logical model merge and for turning on the “sparse mode” for the merge tool in order to improve performance.
In This Topic:
Above we defined a logical model as a set of files consisting of one model file (.emx) and zero to many fragment files (.efx). The reason for this definition is that Model RealTime models often are organized that way, where each logical model constitutes a kind of module which groups related model elements together into a software unit. Because the model elements in a logical model are related, most changes will only affect elements within a single logical model.
However, there will always be some changes that affect more than one model file. For example, if you move a class from one package to another (where each package is the root of their own model file) two different logical models are affected by the change. Running a logical model merge would in this case not be sufficient as it would only look at changes in one of the logical models. Two separate logical model merge sessions would be required and they would report two independent changes (a Delete change in one logical model and an Add change in the other).
To handle this, and similar issues, we need to introduce the concept of model closures. A closure is defined as a set of logical models that somehow belong together. This phrasing is deliberately vague and there are several ways in which the logical models of a closure may belong together:
They may be part of the same workspace
They may be selected by the same working set within a workspace
They may be selected manually by the user in the Project Explorer or some other view
They may be the logical models that were changed as a consequence of making a group of related changes
etc.
A closure is defined by a closure manifest. This is a file with the extension .ecx and it just contains a list of the model files (.emx) that together form the closure. For example, the contents of a closure file containing two models could look like this:
\Project1\ModelA.emx
\Project2\ModelB.emx
If we can obtain the source and target versions of all model files that belong to a closure, then we can merge changes in those source versions to the target versions. This is what we call a closure merge. You can think of it as an extension to logical model merge where we in a single merge session merge not just one logical model, but a list of logical models.
We can of course also compare changes using model closures, and such a compare session is called a closure compare.
A closure manifest is not something you create manually, at least not when invoking a compare or merge from the Model RealTime user interface. Rather it will be created automatically when invoking a closure compare/merge. For a closure merge, all models that have been modified, and hence may need to be merged, will be part of the closure. For a closure compare, the closure is usually taken to be all models present in the workspace, or computed from the selected files or elements.
Closure merge provides the widest possible scope for a merge session. All models that belong to the closure will be loaded in the merge session. This means that the number of merge sessions that have to be launched is significantly reduced compared to logical model merge (and even more so compared to file-by-file merge of course). Consider again the example model mentioned previously:
Model1.emx
Fragment1a.efx
Fragment1b.efx
Model2.emx
Fragment2a.efx
Fragment2b.efx
If all these six files have been modified, it will require six individual file-by-file merges to merge the entire model. With logical model merge two merge sessions are required. With closure merge only one merge session is required (the closure consists of Model1.emx and Model2.emx).
Fewer merge sessions usually means fewer merge conflicts, which makes it easier and quicker to perform the merge. The launching of a closure merge session is more time-consuming than launching a logical model merge session since the contributor and result models will be much bigger. However, if the total time is measured for all merge sessions that are required for merging a set of changes, closure merge is usually faster than both logical model merge and file-by-file merge due to the fewer number of required merge sessions (typically just one with closure merge).
A closure merge session loads the closure in four versions (left and right contributor, ancestor and result model). If the closure is big and consists of many models, this may lead to a high memory consumption for the merge session. If this becomes a concern for you, you may use the preference Enable Sparse Logical Model Merge mentioned above, which reduces the number of loaded files in the same way as it does for logical model merge. Specific CM integrations may have additional preferences for optimizing the performance of closure compare/merge for a particular CM system.
Logical model and closure compare is currently only supported for Git (from the EGit integration user interface and from the command-line). In all other cases when you run a compare session, you will compare model files individually (i.e. a file-by-file compare).
The EGit integration provides a more fine-grained control over logical models than the general on/off preference General - Compare/Patch - Modeling Compare/Merge - Logical Model Settings - Disable Logical Model Synchronization. With EGit you can either choose for each compare session what kind of compare to use, or you can configure it to always use a particular kind of compare. In the preference page Team – RSx EGit Integration you can choose between the following ways to select the kind of compare:
Determine compare kind from selected model element or file
In this case the compare kind depends on what you have selected when running a compare command. If you have selected a fragment file (.efx), or a model element stored in a fragment file, a file-by-file compare session will be launched. If you have selected a model file (.emx) or a model element stored in a model file, a logical model compare session will be launched (for the logical model of that model file).
Determine compare kind using a dialog In this case Model RealTime will pop up a dialog when you run a compare command, asking you what kind of compare session to launch:
This is the default behavior, and it allows you to select the kind of compare each time you run a compare command.
Use file-by-file compare
Always launch file-by-file compare sessions.
Use logical model compare
Always launch logical model compare sessions.
Use closure compare
Always launch closure compare sessions.
Note that this preference is only used when launching a compare session based on a single selected model element or file. If you have selected multiple model elements or files, a closure compare is always launched. The closure is then a list of logical models to which the selected elements belong.
The title of the Compare editor tells you what kind of compare that was launched. Here are some examples:
File-by-file compare session:
Logical model compare session:
Closure compare session:
To launch a logical model or closure compare session from the command-line (or from a script) you should use the cmcmdline.jar Command Line Tool for Compare/Merge.
The compare session will take place in an instance of Model RealTime that is running on the machine (or it can be automatically launched first). It is currently not supported to perform a non-visual logical model or closure compare. Hence the xcompare
parameter must be used. Use the -kind
parameter to specify the kind of compare to perform ('logical' or 'closure'), and use the -source
parameter to specify the source version. Note that currently it's only supported to compare the source version with the current contents of the workspace of the Model RealTime instance that performs the compare operation. Therefore, if you use the -target
parameter it will be ignored.
For example, here is the command to use to perform a logical model compare between the version tagged by “MYTAG” and the current contents of the workspace in Model RealTime:
java -cp cmcmdline.jar com.ibm.xtools.comparemerge.cmcmdline.CMTool xcompare -kind logical -source MYTAG
When launching a logical model compare session exactly one logical model of the source and target versions will be compared. If the source or target versions contains multiple logical models you need to specify which one to compare using the -filter
parameter. Otherwise you will get an error message similar to this:
Multiple logical models found for pattern : HEAD
Please refine your command.
For a closure compare multiple logical models can be compared. In this case you can use the -filter
parameter to specify which logical models that should be part of the closure that is compared. For example:
java -cp cmcmdline.jar com.ibm.xtools.comparemerge.cmcmdline.CMTool xcompare -kind closure -source HEAD -filter="\*Project.emx"
The compared closure will consist of all logical models where the model filename ends with “Project.emx”.
Logical model merge is supported both by the ClearTeam Explorer user interface (for ClearCase) and the EGit user interface (for Git). It's also supported from the command-line (for both ClearCase and Git). Closure merge is supported by the EGit user interface (for Git). It's also supported from the command-line (for both ClearCase and Git).
It is possible to initiate a merge in many different ways with ClearCase. In most of these you request a merge of a single file, and then a file-by-file merge session will be launched. This is true both when you interact with ClearCase directly, using its own user interface or command-line tools, as well as when you use the ClearTeam Explorer user interface within Model RealTime for performing the merge. Here are some examples of such situations which all launch merge of a single file:
When merging from the command-line using the command cleartool findmerge
.
When merging using the Version Tree Browser in the ClearCase user interface.
When merging using the command Merge to View Selected Version in the ClearCase Version Tree view provided by the ClearTeam Explorer plugin within Model RealTime.
To merge an entire logical model, or several logical models, you must initiate the merge in a way that does not specify individual file versions, but rather point out a source and target context for the merge. By "context" here we mean a view, a label or a branch - concepts in ClearCase which groups related versions of multiple files together. Follow these steps to launch a logical model merge session with ClearTeam Explorer:
Ensure that you use a workspace that contains file versions from the target context (a ClearCase view).
Switch to the ClearTeam Explorer perspective.
Expand "My Views" in the ClearTeam Navigator and right-click on the target view.
Invoke the command ClearCase Merge Search from the context menu which launches a merge wizard. On the first wizard page just check that the target view you selected is shown as the destination view. Then proceed by clicking Next.
On the next wizard page mark "Select elements to consider for the merge" and choose the scope of the merge search, for example a particular project folder.
On the next wizard page mark "Merge elements selected by a source view" and choose the source view for the merge (i.e. the view that selects the file versions you want to merge from).
As seen in the dialog it is also possible to select the source files by specifying a branch or a label instead of a view. However, using a view is recommended as it is less error-prone and usually more convenient. If you use a branch you must ensure that all files have versions on that branch, and if you use a label you must ensure that all source file versions are correctly labelled.
Note that currently ClearTeam Explorer does not support to merge from source file versions that are checked out. Therefore, ensure that the files that are selected by the source view are all checked in before you proceed with the merge.
Set appropriate merge options at the bottom of this wizard page and then press ”Finish” to start merging.
All logical models for the files that are selected by the source view will be merged. There will be one merge session launched in Model RealTime for each logical model to be merged.
Just like for compare, the EGit integration has a preference in the preference page Team – RSx EGit Integration for choosing between different ways to select the kind of merge:
Determine merge kind using a dialog: In this case Model RealTime will pop up a dialog when you run a merge command, asking you what kind of merge session to launch:
This is the default behavior, and it allows you to select the kind of merge each time you run a merge command.
Use file-by-file merge: Always launch file-by-file merge sessions.
Use logical model merge: Always launch logical model merge sessions.
Use closure merge: Always launch closure merge sessions.
There is a similar preference for setting the kind of merge used when launching the Merge tool. Normally you will want to use the same kind of merge both for the Merge Model
and the Merge Tool
commands. If you use logical model merge for Merge Model
, then conflicts are reported per logical model. This means that all files in the logical model will be marked as conflicting regardless of in which files exactly the conflicts are located. In the same way, when using closure merge the entire closure will be marked as conflicting.
To launch a logical model merge session from the command-line (or from a script) you need to use the ClearCase type manager application. It is called XtoolsTypeManager and is one of two Compare/Merge command-line tools provided by Model RealTime (see Command Line Tool for Compare/Merge).
Launch the type manager like this to perform a logical model merge (example for Windows):
XtoolsTypeManager.exe xmerge -logicalmerge -sourcecontext <SOURCECTX> -targetcontext <TARGETCTX> -workspace <TARGETWORKSPACE>
Here <SOURCECTX>
should be the name of a ClearCase view that selects the source versions of the files to be merged. All logical models for these files will be merged, and the versions of the files selected by the specified view will be used. If you don't want to merge versions of files selected by a view, you can instead set a label on those file versions that you would like to merge, and then use the label name as the source context. It is also allowed to use the name of a ClearCase branch as the source context, and then the latest versions of all files on that branch will be merged. However, just as is the case when launching logical model merge from the user interface, it is recommended to use a view as the source context.
<TARGETCTX>
must be the name of a ClearCase view that selects the target versions of the files to be merged. Here only a view is allowed, and you cannot use the name of a branch or label for the target context. The reason is that only a view allows to specify the rules (using the config spec) needed to know how to create the new versions for the merged files.
Just like when merging from the user interface you should have the files from the target context in your Model RealTime workspace. The path to this workspace is what should be set as -workspace
parameter.
The initial argument xmerge means that all logical models will be merged visually using the merge tool in Model RealTime. This is recommended since it allows you to review all merge result models. If you instead use the argument merge then there will be automatic merges for all logical models without conflicts, and the merge editor will only appear for those logical models where conflicts are detected. Only use this if you are certain there are no logical conflicts in the merged models.
To perform a closure merge you run XtoolsTypeManager in almost the same way, except that you set the -closuremerge
flag:
<XtoolsTypeManager> merge -closuremerge -sourcecontext <SOURCECTX> -targetcontext <TARGETCTX> -workspace <TARGETWORKSPACE>
The -workspace
parameter is mandatory when performing a closure merge, and there must be a running instance of Model RealTime with that workspace loaded.
It is recommended to run closure merge by launching the XtoolsTypeManager from a script. Such a script can automatically construct a target workspace that contains all model files that should be merged. It can then launch Model RealTime on that workspace, before finally launching the closure merge session.
The closure gets automatically generated based on the target workspace that is specified. The name of the generated closure manifest file (.ecx) shows up in the title of the merge editor in Model RealTime:
If you look at changes or conflicts in one of the Explorer tree viewers you will see that it contains each model of the closure as a root:
There are also a few other parameters that are supported by XtoolsTypeManager. Type
XtoolsTypeManager.exe merge --usage
to print detailed information about all parameters that are supported. For example, there is a parameter -unattended
which can be used for situations when no user is available to handle merge conflicts (for example when the command is run from a nightly scheduled script). This parameter forces a non-visual merge for all logical models, and if there are conflicts these are written to a log file (specified by means of a -logfile
parameter) which can be examined manually at a later point in time.
To launch a logical model or closure merge session from the command-line (or from a script) you should use the cmcmdline.jar Command Line Tool for Compare/Merge.
The merge session will take place in an instance of Model RealTime that is running on the machine (or it can be automatically launched first). Use the -kind
parameter to specify the kind of merge to perform (“logical” or “closure”). If conflicts are found files will be marked as conflicting according to the selected kind of merge. For example, for logical model merge all files in a logical model will be marked as conflicting if at least one conflict is found for the logical model. The -source and -target
parameters should specify the source and target versions for the merge. The latter parameter is optional and defaults to the current contents of the workspace of the Model RealTime instance that performs the merge operation.
As an example, here is the command for performing a logical model merge from the “feature3” branch to the “master” branch:
java -cp cmcmdline.jar com.ibm.xtools.comparemerge.cmcmdline.CMTool merge -kind logical -source feature3 -target master
If you instead use the xmerge
parameter the Merge tool will be launched immediately after the merge has finished, if conflicts were found.
Here is an example of launching a closure merge from the version selected by the tag “pre-master” to the “feature3” branch.
java -cp cmcmdline.jar com.ibm.xtools.comparemerge.cmcmdline.CMTool xmerge -kind closure -source pre-master -target feature3
The closure is by default all logical models that have changes when comparing the source and target versions. You can define the closure more specifically using a closure manifest file (.ecx) and the -manifest
parameter.