The method Node.merge can be thought of as a version-sensitive Node.update. It works as follows:
The merge method can be called on a versionable or non-versionable node.
Like update, merge does not respect the checked-in status of nodes. A merge may change a node even if it is currently checked-in.
If this node (the one on which merge is called) does not have a corresponding node in the indicated workspace, then the merge method returns quietly and no changes are made.
If this node does have a corresponding node, then the following happens:
For each versionable node N in the subtree rooted at this node, a merge test is performed comparing N with its corresponding node in srcWorkspace, N'.
The merge test is done by comparing the base version of N (call it V) and the base version of N' (call it V').
For any versionable node N there are three possible outcomes of the merge test: update, leave or failed.
If N does not have a corresponding node then the merge result for N is leave.
If N is currently checked-in then:
If V' is a successor (to any degree) of V, then the merge result for N is update.
If V' is a predecessor (to any degree) of V or if V and V' are identical (i.e., are actually the same version), then the merge result for N is leave.
If V is neither a successor of, predecessor of, nor identical with V', then the merge result for N is failed. This is the case where N and N' represent divergent branches of the version graph, thus determining the result of a merge is non-trivial.
If N is currently checked-out then:
If V' is a predecessor (to any degree) of V or if V and V' are identical (i.e., are actually the same version), then the merge result for N is leave.
If any other relationship holds between V and V', then the merge result for N is fail.
If bestEffort is false then the first time a merge result of fail occurs, the entire merge operation on this subtree is aborted, no changes are made to the subtree and a MergeException is thrown. If no merge result of fail occurs then:
Each versionable node N with result update is updated to reflect the state of N'. The state of a node in this context refers to its set of properties and child node links.
Each versionable node N with result leave is left unchanged, unless N is the child of a node with status update and N does not have a corresponding node in srcWorkspace, in which case it is removed.
If bestEffort is true then:
Each versionable node N with result update is updated to reflect the state of N'. The state of a node in this context refers to its set of properties and child node links.
Each versionable node N with result leave is left unchanged, unless N is the child of a node with status update and N does not have a corresponding node in srcWorkspace, in which case it is removed.
Each versionable node N with result failed is left unchanged except that the UUID of V' (which is, in some sense, the “offending” version; the one that caused the merge to fail on that N) is added to the multi-value REFERENCE property jcr:mergeFailed of N. If the UUID of V' is already in jcr:mergeFailed, it is not added again. The jcr:mergeFailed property never contains repeated references to the same version. If the jcr:mergeFailed property does not yet exist then it is created. If present, the jcr:mergeFailed property will always contain at least one value. If not present on a node, this indicates that no merge failure has occurred on that node. Note that the presence of this property on a node will in any case prevent it from being checked-in because the OnParentVersion setting of jcr:mergeFailed is ABORT.
This property can later be used by the application to find those nodes in the subtree that have failed to merge and thus require special attention (see 8.2.10.2 Merging Branches, immediately below). This property is multi-valued so that a record of successive failed merges can be kept.
In either case, (regardless of whether bestEffort is true or false) for each non-versionable node (including both referenceable and non-referenceable), if the merge result of its nearest versionable ancestor is update, or if it has no versionable ancestor, then it is updated to reflect the state of its corresponding node. Otherwise, it is left unchanged. The definition of corresponding node in this context is the same as usual: the match is done by UUID (for a referenceable nodes) or UUID plus relative path (for non-referenceable nodes).
Note that as a result of the final rule, above, a merge performed on a subtree with no versionable nodes at all (or indeed in a repository that does not support versioning in the first place) will be equivalent to an update.
The merge method returns a NodeIterator over all versionable nodes in the subtree that received a merge result of fail.
Note that if bestEffort is false, then merge will either return an empty iterator (since no merge failure occurred) or throw a MergeException (on the first merge failure that was encountered).
If bestEffort is true, then the iterator will contain all nodes that received a fail during the course of this merge operation.