This document details Subversion's merge tracking requirements and their supporting use cases, the majority of which are driven by Subversion's Developer and Merge Meister users. A few outliers are driven by SCM automation.
log
and blame
)Track which changesets have been applied where, so users can repeatedly merge branch A to branch B without having to remember the last range of revisions ported. This would also track changeset cherry picking done by users, so we don't accidentally re-merge changesets that are already applied. This is the problem that svk and arch claim to have already solved, what they're calling star-merge.
Merge of one or more individual changes from branch A into branch
B. This sometimes involves manual application of the changes from rN
in branch A (e.g. not using svn merge
), or manual
adjustment of a change merged into a WC before it's committed to the
repository. Regardless of the merge method used, Subversion must
provide a way to indicate that the change(s) have been merged into
branch B.
Additionally, it's important to be able to cherry pick changes in multiple different directions. For example, if you create a release branch B by copying the trunk you should be able to both forward port changes made on B into trunk and backport changes made on trunk into B without confusing the merge tracking algorithm.
Use may be predicated on information from the Show Change Sets Available for Merge feature (Auditing section).
svn merge
needs to handle renames better. This
requires true
rename support.
Edit foo.c on branch A. Rename foo.c to bar.c on branch B.
svn merge
will skip the file, because it can't find
it.svn
merge
will delete the 'newer' version of foo.c and add bar.c,
which has the older text.Problem #2 stems from the fact that we don't have true renames, just copies (with history) and deletes. That's not fixable without a FS schema change, and (probably) a libsvn_wc rewrite.
It's not clear what it would take to solve problem #1. See the discussion about our rename woes, and the relationship to merge tracking.
Allow change sets to be marked as merged, effectively a way to manipulate the merge memory on a source and destination. This is related to the revision blocking concept.
Fundamentally, the use case is to support merge tracking of change
set which is sufficiently different when ported to a different branch
that use of svn merge
is no longer appropriate. Examples
scenarios include:
David James cites a specific example from Subversion's own development:
"When I merge from trunk to 1.3.x, I often run into conflicts, so I create a temporary merge branch. If I tried to merge from the temporary merge branch to 1.3.x, the merge metadata would be lost because svnmerge.py does not track indirect metadata. To correct this metadata, I'd use [this feature]."
Use may be predicated on information from the Show Change Sets Available for Merge feature (Auditing section).
Undo a merge and/or associated tracking meta data. Necessary for both automated and manual merges.
Use may be predicated on information from the Show Change Sets Available for Merge and Show Change Sets Already Merged features (Auditing section).
Protect revisions which should never be merged from accidental merging.
Changes to arbitrary properties set on a versioned resource should be mergable exactly as entries within a directory (e.g. add, deleted, etc.), or content in a file (see repeated merge).
Subversion's revision properties (sometimes referred to as revprops) need not be handled.
Merge previews are dry runs that show conflicts and "non-trivial, non-conflicting" (NTNC) changes in advance. These previews should be exportable and parseable. (From the distributable resolution item in the summit summary.)
The ability to automate merges (e.g. from a stable branch to a development branch), including interfaces for resolving conflicts and handling other errors, is important. Merge Meisters who do multi-thousand file merges stress this.
The mechanism for resolving conflicts in a merge should be distributable across N developers. Meeting this requirement might mean a departure for Subversion, since it implies that merge results are not just stored in one working copy, but are somehow available on the server side. (From the distributable resolution item in the summit summary.)
Merge tracking must be audit-friendly, supporting some basic forms of reporting which allow for discovery of following types of information:
svn blame
should show the changed lines in B as
last touched by A, even if the merge was committed by you and you
are not A. This must also work when merging a range of revisions
with different authors.svn log -rN
should show both the original
author A, and the author who merged the change.Whatever solution is chosen must play well with svnadmin
dump
and svnadmin load
. For example, the metadata
used to store merge tracking history must not be stored in terms of
some filesystem backend implementation detail (e.g.
"node-revision-ids") unless, perhaps, those IDs are present for all
items in the dump as a sort of "soft data" (which would allow them to
be used for "translating" the merge tracking data at load time, where
those IDs would be otherwise irrelevant). See issue
1525 about user-visible entity IDs.
(This was one of the points made at the EuroOSCON 2005 Version Control BOF session.)
The interface for common-case merges should be easy. Currently it
is not. For example, a very common case is merging all previously
unmerged changes from trunk to branch (more formally, from a source
line to a descendant destination line). Today, one must type
svn merge -rX:Y URL WC
. But why
can't the dest just remember what has been merged from that src before
and do the right thing? Then one could type
svn merge SRC DST
. Or better yet,
branches could remember where they come from, and one could just type
svn merge SRC
, or
svn merge DST
, depending on whether one wants a
push or pull interface. (It was pointed out that SVK does remember
these things; if someone familiar with the SVK interface wants to put
an example transcript here, that would be great.)
Here is the svk command transcript:
A branch creation by:
svk copy //project/trunk //project/branch-B
(or mirroring an existing subversion repository containing such branch)To merge from trunk to branch-B:
svk smerge //project/trunk //project/branch-B
, orsvk smerge --to //project/branch-B
, orsvk pull //project/branch-B
To merge from branch-B back to trunk:
svk smerge //project/trunk //project/branch-B
, orsvk smerge --from //project/branch-B
, orsvk push //project/branch-B
There is also a
-I
flag in smerge to merge changes revision-by-revision. Push is by default with the option, and pull is not.
Another common case is porting a single change from one line to
another. This currently requires -r<X-1>:X
syntax,
but Subversion 1.4 will include the -c
option (introduced
in r17054), so users will no longer need to perform this menial
arithmetic. However, Subversion 1.4 will still require the URL of the
merge source to be specified; a merge tracking solution that eases
common cases would obviate the need for the user to supply the URL
when a single change is ported from a branch's ancestor line.
svk merge also supports -c N
flag which is
-rN-1:N
.
Merge tracking information should be maintained for all versions of files in a repository. Thus, if you create a copy of an old version of a branch, the merge tracking information will still be accurate.
Changes to merge tracking information should be versioned, therefore allowing tracking and auditing of changes to merge tracking data.
Repository administrators should be able to control whether merge tracking information can be committed by specific users or to specific directories.
Repository administrators should be able to control whether changes can be committed without associated merge-tracking information. Using this feature, a repository administrator could enforce (for example) that all changes must be committed to trunk before they are merged to a release branch.