I propose the following logical semantics of the versioned move
operation that is the basis of move tracking, independent of any
A versioned move of the node with node id “N”, with respect to two
revisions rX and rY (X < Y), shall mean:
* Same node id. A node with node id N exists in rX and in rY. It
is “the same node”. It therefore has the same node kind. It may have
* No gap. There cannot be a gap in the range of revisions: node id
N exists in every revision rX, rX+1, …, rY-1, rY. (Contrast with
copy-and-delete, where there can be a gap between the delete and the
copy.) (The possible “resurrection” extension to these semantics
would permit a gap.)
* Move and/or rename. Node N has either or both of: a different
name (base name) in rX than in rY; and/or a different parent (parent
directory node id) in rX than in rY.
* Children follow. If N is a directory, each child (recursively)
of N in rX remains a child of N in rY, with the same name, unless it
is separately moved or deleted. Any or all of the children can be
separately moved within or outside the subtree at N, at the same time
as N is moved.
* No null move. An attempted move which does not change the node's
name or its parent node, with or without a modification, is not
distinguished from a normal succession of history.
=== Move versus Rename ===
In the versioned data model semantics, “move” refers to a change of
parent node and/or a change of name.
At a higher level of semantics, for example when resolving conflicts
during merge, it can be useful to distinguish between renaming and
moving to a different parent node.
=== Can't Move a Child of a Copy ===
Moving a child of a copy, within the same revision, is not tracked: it
is an unversioned operation.
A versioned "move" takes a node that existed in the previous revision
and places it in a new location. A copy, however, always creates new
nodes, conceptually, even if the internal representation is a "lazy
copy" pointer to the old node. Moving a child node therefore is a
rearrangement of the new content. It is semantically the same as
deleting the child node and creating a copy of it somewhere else.
Compare with copying a node and then moving that copy somewhere else.
If we perform a copy and then move a child of it, either in a WC or in
a repository, this should create a copy with a deleted child, and then
another copy somewhere else which is the "moved" child in its new
Is this acceptable? This means that combining the two separately
committed changes "copy" and "move a child" into a single commit will
result in semantic data loss, which we are trying to avoid.
Received on 2013-08-15 17:02:52 CEST