On Tue, Sep 07, 2010 at 12:11:51PM +0300, Vadim wrote:
> Hello,
>
> The situation: file is added and committed to a branch, then the same
> revision
> is merged into trunk. After that, the range of revisions are merged from
> trunk
> back to the same branch which results in a tree conflict on the added file.
> My
> understanding of svn:mergeinfo isn't consistent with this behaviour as, to
> my
> mind, trunk 'knows' that the file originated from the branch and branch
> 'knows' that
> the revision which resulted in the addition of a file had already been
> merged
> into trunk.
No. That's not how it works at all. Subversion doesn't know any of that.
This is quite a common misconception, so let me try to explain the problem:
The way merge-tracking was designed, Subversion treats a path:revision
tuple as the unique identifier for changeset to be merged.
So Subversion doesn't know whether, say, two changesets /branch:30 and
/trunk:42 represent the same semantic change made on different branches
(in your case, the semantic change is "add file foo.c").
To Subversion, these are always different changesets, because they have
different identifiers.
Only the user knows more. But the real problem is that /trunk:42 might contain
more than just the semantic change made in /branch:30. For instance, it might
contain additional changes merged from other branches, or changes made during
conflict resolution. Even from the design point of view, it seems to be
impossible to automatically merge just the part of the /branch:30 changeset
as it appears within the /trunk:42 changeset.
So the whole /trunk:42 change is always merged, leading to conflicts (both
sides say "add this file foo.c"). Because Subversion cannot currently resolve
tree conflicts for the user (it can only detect them), tree conflicts tend
to show up most often in these situations.
But you can also get text conflicts, for example.
There are two ways to deal with this problem:
1)
If you know that /trunk:42 is semantically equivalent to /branch:30,
you can block the /trunk:42 change on the branch, as described here:
http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.blockchanges
Then, the branch can sync to the trunk without running into a conflict,
because the offending revision will be skipped since it has already been
marked as merged. Being able to block revisions like this requires that
developers are disciplined about what changes are made in a single commit.
2)
The only way to completely avoid this problem is to avoid doing cyclic
merges altogether. Make all changes which need to propagate to more
than one branch enter your code base at one clearly defined branch.
For instance, always make bugfixes in the oldest (or newest) active release
branch and merge to other branches from there. Or always make bugfixes in
the trunk and merge it to other branches from there.
However you do it, if you draw your branching/merging strategy as a diagram
showing your branches as horizontal lines and merges as arrows pointing
from one of those lines to another line, you must not get cycles.
Of course, the current behaviour leaves room for improvement.
Once Subversion learns about resolving trivial tree conflicts automatically,
the trivial conflicts like "both sides say add file foo.c with content X"
will be automatically resolved and you'll have less chances of running into
conflicts requiring manual attention during cyclic merges.
However, in general, the problem cannot be solved completely. If you find
a way that makes Subversion automatically handle this problem in the general
case, you've solved a problem that, so far, nobody has been able to figure
out a solution for.
AFAIK there is no open source tool which handles this problem nicely.
Distributed tools suffer from the same problem, because changeset
identifiers are cryptographic hash numbers, and when you cherry-pick changesets
between branches, the tool cannot tell whether any two changes with different
identifiers are semantically equivalent, so you can get conflicts when you
eventually merge the branches.
However, they are currently a bit better than Subversion at handling trivial
tree conflicts automatically, so it's less of an issue in practice.
The only tool I know of which I've been told can do cyclic merging without
much help from the user is clear case (though I have my doubts, maybe it
just has a good UI for this use case?). If you know of any others, please
let me know.
Thanks,
Stefan
Received on 2010-09-07 13:18:34 CEST