Summary: I plan to make 'svn merge' act on --accept=theirs|mine|etc. per file, 
rather than (as it does now) postponing all conflicts until after the whole 
merge and then resolving them.


I have been investigating the way "--accept=foo" resolves conflicts, for 
blocker issue #4238 "merge -cA,B with --accept option aborts if rA conflicts" 
[1].  Postponing all resolution until the end of the whole merge (as we do now) 
is not good enough in this scenario.  A similar scenario can occur during an 
automatic merge when the merge code internally decides to do a 
multi-revision-range merge.


We need to be able to resolve conflicts at least after each phase (revision 
range) of merge.

For the manual '-cA,B' example the client ('svn') could simply call 
svn_client_merge once for each specified revision or range, resolving any 
conflicts after each.  That is not feasible for the ranges decided internally 
during an automatic merge, because the client doesn't have a way to discover 
those ranges in advance.  (And the merge code architecture is such that it 
discovers those ranges incrementally as it goes.)

I suppose the client could run the merge, let the merge abort if it finds any 
conflicts during a phase, resolve those conflicts, and then run the same merge 
again, repeating until the merge is complete.  That may work if the merge code 
can be run again and again... but it isn't set up to do so in general.  (For 
one thing, local mods aren't tolerated in all cases, and obviously there will 
be local mods after the first phase has run.  I bet there would be other 
problems too.)

I think a good enough solution for 1.8 is this:

  * With --accept=postpone, if any conflicts are raised during a merge phase 
(one revision range), then abort the merge after that phase.  (The details are 
not relevant to this mail thread.)

  * Otherwise, the user requested a specific conflict resolution.  At the 
moment, we run the merge with a per-node resolver callback installed that 
always chooses 'postpone' but also collects a list of the conflicted paths, and 
then we run 'resolve' on those paths afterwards.  Instead, let 
the resolver callback be active during the merge, resolving each 
conflict on a node immediately after that conflict has been raised, according 
to '--accept'.

  * By resolving a conflict so soon, we can avoid notifying the merge result as 
'C' for conflict and instead notify 'U' or 'G' for that node, and avoid 
"Resolved conflict on 'foo'" lines.  I think that is better.

  * After the merge, there might still be some postponed conflicts, depending 
on whether the implementation of the chosen --accept was capable of handling 
every conflict that occurred.  We might want to consider doing something like 
running the interactive resolver afterwards if this happens, but I think not.

The main alternative I can think of to this plan would be to design a way to 
store multiple 
conflicts (of the same kind) per node and so be able to postpone all conflicts 
from multiple phases of merge.  We have decided before that that
 is too difficult and I still think so.

So, can you see any problems with the above approach?

I think we were doing this at one stage during development.  I assume we 
stopped because (a) for interactive resolution, postponing that stage until 
after the merge avoids network timeouts due to waiting for the user; and (b) we 
wanted to test the ability to postpone all conflicts and/or there seemed to be 
no reason to make the '--accept=' case work differently from the interactive 
case.

- Julian


[1] <http://subversion.tigris.org/issues/show_bug.cgi?id=4238>

--
Certified & Supported Apache Subversion Downloads: 
http://www.wandisco.com/subversion/download

Reply via email to