This is not part of the official documentation of Subversion. It is aimed at the developers of Subversion, and may not reflect reality or the project community's plans. For official documentation, see .

The aim of this page is to hold initial design notes and ideas on all of the topics relevant to the theory of merge tracking, in the context of enhancing merge support in Subversion after 1.8. It does not aim to comprehensively cover each topic.

Per Node or Per Tree Semantics

A 'branch' consists of a set of nodes at any given time, but the set of nodes is not fixed, it varies over time. Nodes can be added and deleted. (Can a node be moved into or out of a branch? What does it mean?)

Therefore, asking 'what changes have been made on branch A?' involves more than querying merge history for each node that is *currently* on branch A. Or does it? If every tree change (especially add, delete) is modelled as a change of the parent directory, then perhaps all the information is necessarily present just by querying the history of the current set of nodes on the target branch.

Relationships Between Branches

See Perforce's "Merge Down, Copy Up".

See Perforce's "Streams". Stream types: mainline, development, release. Stream policies: "merge down, copy up".

Does Mercurial have something towards this?


Fast-forward merge should:

Unrelated Changes

Theory of committing an unrelated change along with a merge.

I think, to make sense of arbitrary merging across multiple branches, unrelated changes should not be supported. (They should be seen as part of conflict resolution.) Then, changes can be merged physically from any convenient branch in the graph. If an unrelated change is required to be "tracked" (treated as a logical change that must be merged to the target branch), then all required changes in a merge have to come physically from the specified source branch.

Doug Robinson said, for criss-cross, we must assume user may have committed an unrelated change each time, and therefore the two branches cannot be considered equivalent until either a complete merge is done one way or the user explicitly tells the VCS that the branches are equivalent.


Theory of tracking cherry-pick merges as well as full merges.


From [NewMerge]: "If you want to work on a subtree, you can make a new branch [...] that contains the subtree. We can track its relationship and merge it back to the complete tree."

Merge Each Rev-Range or Merge Each File?

Presently, Svn breaks a multi-rev-range merge into rev ranges, and the outer loop is over those ranges. An alternative is for the outer loop to be over the nodes. Advantages: splitting the merge of a single node into sub-ranges can produce spurious conflicts; merging each file in as few sub-ranges as possible avoids this.

Discussed in (one of my Wiki pages on Merge, I think) and (an old dev@ email, from Daniel Rall?).

An additional option is to merge each file according to its own merge graph, by which I really mean choosing a merge base in the node's own graph, which, if the node has had its own subtree merging, might not be where the branch root's base is. Is such a merge semantically the same as if it were done according to the branch root's merge graph? I'm thinking of the semantic subtleties such as whether unrelated changes are propagated as expected, and how reverse-merges and blocked merges are handled.

If we merge each tree according to its own graph (and if that has different semantics from merging them all using the branch root's graph), then that means we are treating each node the same as each other node, with no special treatment of a branch root. That may or may not be a Good Thing. That is a characteristic of file-based VCS's.

Reverse Merge, Blocked Merge

Idea of differentiating between "un-merging" and "blocking" changes. They have different semantics:

Continue after Conflicts?

Can Svn do more to enable merging to continue after hitting conflicts? Presently it stops at the end of whichever revision range it is processing.

Criss-Cross & Recursive Merge

Recursive merge strategy can resolve a criss-cross -- see the explanation linked below.

How could we implement the "recursive merge" strategy in Subversion?

Node-Matching Semantics

Ways to match nodes in source branch (A) & target (B):

  1. explicit (node-id)
  2. last merge
  3. last *complete* merge
  4. previous merges
  5. natural history, if any

Different possible ways to model mergeinfo that connects to previously unconnected nodes:

Vendor branches

How to link two previously unrelated branches? Various vendor-branch scenarios have this requirement initially, if the local copy of the vendor's branch was not created by a first-class copy operation from the original.

This should be supported by a degenerate form of merging: an operation that sets the mergeinfo as if "all merges on A up to r100" had been merged into B. The operation should match nodes by the fall-back methods such as child-name matching and potentially content matching, and allow the user to edit the result. For example, Subversion could say "all nodes in A and B have been matched by name, except for these in A (...) and these in B (...)", and offer something akin to tree conflict resolution to allow the user to choose which of the remaining ones are adds, deletes, renames, etc.

Foreign Repository


Can merge history store enough info about a foreign branch so that we can calculate & use the latest available (currently accessible) common acncestor? So, if branch X is in a "foreign" repo and branches A, B are in a "local" repo, and we have merged A <-> X <-> B, can we than merge A <-> B if we are unable to contact X?


This page was written initially by JulianFoad and may be edited by others.=~