You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Daniel Rall <dl...@collab.net> on 2006/11/21 19:35:01 UTC

Merge conflict resolution

Hello Subversion IDE developers.  I'm currently working on building
Merge Tracking support for Subversion.  As part of this journey, I've
discovered that writing merge conflict markers into a file isn't
conducive to a friendly user experience when applying multiple
revision ranges during a single merge operation (or otherwise, for
that matter :).  I need to allow for a better way of handling merge
conflict resolution in Subversion, and I'd like your help in assuring
that this is designed from the ground up with Subversion IDEs in mind.


Background:

While conflict markers might not currently seem like much of a problem
to most people (at least, to those not grumbling that Subversion is
"corrupting their files"), Merge Tracking really complicates things.
In today's Subversion, we apply only one revision range during any
merge operation.  With Merge Tracking, we may apply multiple revision
ranges during a single merge operation, a rather fundamental
difference with many ramifications.  Once a file has a merge conflict,
we have to stop applying revision ranges, meaning that we might apply
only a portion of the revisions requested for merge by the user.
Improved merge conflict resolution handling will really help address
this user experience.


Requirements:

- Allow merge conflicts to be resolved during application of a merge.

- Allow as much automatic merging to be performed as possible without
requiring human interaction.

- Allow declarative conflict resolution to avoid any human interaction
(e.g. --resolve-conflict-using=[older|theirs|mine]), supporting some
degree of conflict resolution from merges (e.g. build automation).

- Maintain compatibility with the diff3 command.

- Allow for resolution more types of conflicts (e.g properties,
obstructions, etc.).


Possible implementation:

Subversion will first attempt a merge via its built-in diff library,
or the diff3 command specified in its config file (or via the
--diff3-cmd option, for the command-line client).  If a merge conflict
occurs to either content (file or directory) or properties, it will
invoke a merge conflict resolution callback provided via its
svn_client_ctx_t structure (we may provide a default implementation of
this which calls out to an external binary a la the diff3 command used
in the original merge).  This callback would prompt the user to
resolve the conflict (when in non-interactive mode), and upon
resolution allow subsequent merge of revision ranges to occur into the
same file (important for Subversion's Merge Tracking support).  For
the command-line client, the callback would throw up a prompt
something like:

  Merge conflict detected for "foo.c" at line 37
  mine:
   struct iovec vec;
  theirs:
   int k;
  older:
   int i;
  Retain (m)ine, (t)hiers, or (o)lder version? _

IDEs could obviously do something even more user-friendly, throwing up
a three-way merge GUI like TortoiseMerge, WinMerge, Araxis Merge,
etc., but ONLY when a merge conflict actually occurs.

If the callback notes that the conflict was resolved, its WC state
will be automatically changed accordingly.


Question for IDE developers:

I'm really curious how IDEs handle this situation today.  Taking
TortoiseSVN as an example, I've heard that its TortoiseMerge diff3
program is great for conflict resolution (though currently lacking an
edit mode), but not so great for performing merges of a large number
of changes (e.g. merging changes from trunk into a feature branch),
especially when the majority of those changes can be applied
automaticaly with no merge conflicts (and thus don't need typically
need a merge GUI).  Is this an issue for TortoiseSVN/TortoiseMerge
today, or am I out of date?  How about for other IDE developers?  How
do you guys handle this today?  ;-)

Re: Merge conflict resolution

Posted by Daniel Rall <dl...@collab.net>.
Thanks for the thoughtful and detailed response, Stefan.

On Wed, 22 Nov 2006, Stefan Küng wrote:

> Daniel Rall wrote:
> 
> >While conflict markers might not currently seem like much of a problem
> >to most people (at least, to those not grumbling that Subversion is
> >"corrupting their files"), Merge Tracking really complicates things.
> >In today's Subversion, we apply only one revision range during any
> >merge operation.  With Merge Tracking, we may apply multiple revision
> >ranges during a single merge operation, a rather fundamental
> >difference with many ramifications.  Once a file has a merge conflict,
> >we have to stop applying revision ranges, meaning that we might apply
> >only a portion of the revisions requested for merge by the user.
> 
> What happens if such a conflict would not exist anymore if all revision 
> ranges got applied? I'm thinking of a situation where the same line got 
> changed multiple times over multiple ranges, and the last change would 
> render the file so that no conflict would occur.
> Does it create a conflict which has to be resolved or will that be 
> handled 'gracefully'?

The current implementation on the merge-tracking branch does not
handle this situation in the manner you describe above.  We basically
wrap the guts of 'merge' in a loop, apply one revision range at a time
to the WC (as if you'd run 'merge' multiple times), recording merge
history incrementally as we go.

Truthfully, I have a hard time imagining how to successfully implement
what you describe above.  Any ideas?

I'm really open to anything here, including a completely different
approach than my suggested conflict resolution callback.


> >Requirements:
> >
> >- Allow merge conflicts to be resolved during application of a merge.
> >
> >- Allow as much automatic merging to be performed as possible without
> >requiring human interaction.
> >
> >- Allow declarative conflict resolution to avoid any human interaction
> >(e.g. --resolve-conflict-using=[older|theirs|mine]), supporting some
> >degree of conflict resolution from merges (e.g. build automation).
> >
> >- Maintain compatibility with the diff3 command.
> >
> >- Allow for resolution more types of conflicts (e.g properties,
> >obstructions, etc.).
> 
> Will it be possible to have it work like before? Without user
> interaction *during* the merge but get conflicted files which must
> be resolved later?

As currently implemented on the merge-tracking branch, user
interaction is avoided for (internal) merges of revision ranges up
until there is a conflict.  When a conflict occurs, merging of
subsequent revision ranges is stopped.

I'm proposing we inject as-needed conflict resolution so that it's
possible to apply the entire set of requested revision ranges.  This
does not completely remove the problem -- an unresolved conflict may
leave us in same situation, with potentially only a portion of the
requested revisions applied by the merge.

Let's say I run 'svn merge -r 3:10 $src_url' into a WC which has
already had revisions 4-6 and 8-9 from $src_url merged into it.  This
leaves revisions 3, 7, and 10 yet to be merged.  Today on the
merge-tracking branch, if 7 yields a conflict, revision 10 is never
applied (this happens silently).  This is a major departure from the
current behavior, effectively changing 'merge' to accept multiple
revision ranges and suffering the consequences.  This is the problem
I'm trying to solve.

> I'm thinking of situations with flaky network connections, where a user 
> might want to do the merging in one step without interruption, and then 
> do the resolving later.
> In which state of the merge is the callback called? Just to avoid 
> timeout errors when the user takes too long to resolve such a conflict 
> during the merge operation.

Garrett Rooney and Madan S. had a similar concern.  A network timeout
could potentially occur.  However, applying only a portion of the
requested merge seems less than ideal.  Do you have a better idea how
to handle the scenario I describe above?  I'm all ears.  :-)

> >Possible implementation:
> >
> >Subversion will first attempt a merge via its built-in diff library,
> >or the diff3 command specified in its config file (or via the
> >--diff3-cmd option, for the command-line client).  If a merge conflict
> >occurs to either content (file or directory) or properties, it will
> >invoke a merge conflict resolution callback provided via its
> >svn_client_ctx_t structure (we may provide a default implementation of
> >this which calls out to an external binary a la the diff3 command used
> >in the original merge).  This callback would prompt the user to
> >resolve the conflict (when in non-interactive mode), and upon
>                                 ^^^
> :)

Yup -- *interactive*, thanks.

> >resolution allow subsequent merge of revision ranges to occur into the
> >same file (important for Subversion's Merge Tracking support).  For
> >the command-line client, the callback would throw up a prompt
> >something like:
> >
> >  Merge conflict detected for "foo.c" at line 37
> >  mine:
> >   struct iovec vec;
> >  theirs:
> >   int k;
> >  older:
> >   int i;
> >  Retain (m)ine, (t)hiers, or (o)lder version? _
> 
> I suggest to include the line numbers there. Otherwise it may be hard 
> for the user to find out where exactly in the files that context is.

I agree (this is just an example, not something I've implemented).
Perhaps something like:

  Merge conflict detected for "foo.c":
  mine (line 37):
   struct iovec vec;
  theirs (line 36):
   int k;
  older (line 32):
   int i;
  Retain (m)ine, (t)hiers, or (o)lder version? _

> >Question for IDE developers:
> >
> >I'm really curious how IDEs handle this situation today.  Taking
> >TortoiseSVN as an example, I've heard that its TortoiseMerge diff3
> >program is great for conflict resolution (though currently lacking an
> >edit mode), but not so great for performing merges of a large number
> >of changes (e.g. merging changes from trunk into a feature branch),
> >especially when the majority of those changes can be applied
> >automaticaly with no merge conflicts (and thus don't need typically
> >need a merge GUI).  Is this an issue for TortoiseSVN/TortoiseMerge
> >today, or am I out of date?  How about for other IDE developers?  How
> >do you guys handle this today?  ;-)
> 
> If the callback provides the information so that the UI merge tools
> can use whole files, this will work ok. If however the callback only
> provides the context of the file where the conflict occurs, we'd
> have to write a custom merge tool just for this purpose - which is
> maybe not such a bad idea anyway.

I'd prefer the callback to be usable by invoking third-party merge
tools (e.g. the TortoiseMerge GUI), so supporint use of whole files
seems like the way to go.  A custom merge implementation could
interrogate the files for more context (e.g. like the command-line
version shown in the example above).

> [copied from other mail]
> > I'm assuming that the callback will take care of doing the actual
> > merge, and that Subversion libraries will handle the WC meta data
> > manipulation.  Here's the API I've integrated in the tree delta editor
> > (from libsvn_client/repos_diff.c); I may actually want to push this
> > deeper, down into the WC's editor:
> 
> Is the Subversion internal diff3 called first and this callback only 
> called if there is a conflict?

That's what I'd recommend.  As today, you could always use a custom
diff3 command (e.g. GNU diff), which has an interface contract
allowing it to communicate conflict status back to Subversion by way
of exit codes:

http://svnbook.red-bean.com/en/1.2/svn.advanced.externaldifftools.html

Regardless of diff3, the conflict resolution callback would only be
invoked if the initial diff3 command indicated that a path was in
conflict after the merge attempt.

> > /** A callback used for resolving merge conflicts to content or
> >  * properties encountered during the application of a tree delta to a
> >  * working copy.
> >  *
> >  * This callback is only invoked when not in "dry run" mode.  It
> >  * provides for a smooth balance of automated merging via a
> >  * non-interactive diff3 mechanism like Subversion's internal
> >  * implementation (or an external tool like GNU diff specified via @c
> >  * SVN_CONFIG_OPTION_DIFF3_CMD), and declarative or interactive merge
> >  * conflict resolution (e.g via an external tool like TortoiseMerge or
> >  * Araxis Merge).
> >  *
> >  * If @a content_state and/or @a prop_state are not @c NULL, and the
> >  * conflict is resolved during the callback, set @a content_state
> >  * and/or @a prop_state appropriately (e.g. likely to @c
> >  * svn_wc_notify_state_merged); housekeeping for the resolution of @a
> >  * path will occur automatically.  If @a content_state and/or @a
> >  * prop_state are not @c NULL but returned unchanged, it's assumed
> >  * that the conflict has not been resolved.
> >  *
> >  * All allocations should be performed in @a pool.
> >  *
> >  * @a baton is a closure object; it should be provided by the
> > implementation,
> >  * and passed by the caller.
> >  *
> >  * @since New in 1.5.
> >  */
> > typedef svn_error_t *(*svn_client_conflict_resolver_func_t)
> >   (const char *path,
> >    svn_wc_notify_state_t *content_state,
> >    svn_wc_notify_state_t *prop_state,
> >    svn_boolean_t dry_run,
> >    void *baton,
> >    apr_pool_t *pool);
> 
> I see that this callback only has one 'path' parameter. I don't see 
> where the information would be to actually do a merge? Doesn't a merge 
> require at least three files/paths to actually get a conflict which must 
> be resolved?

In my prototyping, I made the simplifying (for me :) assumption that
the other paths could be extrapolated from the FS path (using some
Subversion svn_wc.h API, I'm guessing).  Putting three paths into the
API signature would make it simpler to implement, though.

> Some other thoughts:
> * sometimes it's not possible to resolve a conflict without modifying 
> also other files (not just the one which has the conflict). Will it be 
> possible for the UI merge tool to just tell "sorry, can't resolve this" 
> and Subversion will then behave as before and leave the file conflicted?

Yes, as with custom diff3's.  On the merge-tracking branch, this has
the consequences described above (potential partial merge).  On
Subversion's trunk, it would behave as today.

> * it would be nice if the svn:mime-type property value also is passed to 
> the callback: UI tools could use this information to find out what the 
> best way would be to resolve a conflict or just to simply adjust the UI 
> according to the mime type

Good suggestion.  What if the path in conflict is a directory?  What
if it's the path's properties that are in conflict?  Should we still
pass in the MIME type?

> * if the callback does not provide only the context where the conflict 
> occurs but whole files, an information is required where Subversion can 
> not resolve the conflict itself: UI merge tools may use a different 
> diff3 algorithm which won't see a conflict where Subversion sees one. 
> Maybe the line numbers of where the conflict is supposed to be.

So, in addition to the whole file, some additional context describing
where Subversion found a conflict.  How do we handle this when a
custom diff3 implementation is used?

Re: Merge conflict resolution

Posted by Stefan Küng <to...@gmail.com>.
Daniel Rall wrote:

> While conflict markers might not currently seem like much of a problem
> to most people (at least, to those not grumbling that Subversion is
> "corrupting their files"), Merge Tracking really complicates things.
> In today's Subversion, we apply only one revision range during any
> merge operation.  With Merge Tracking, we may apply multiple revision
> ranges during a single merge operation, a rather fundamental
> difference with many ramifications.  Once a file has a merge conflict,
> we have to stop applying revision ranges, meaning that we might apply
> only a portion of the revisions requested for merge by the user.

What happens if such a conflict would not exist anymore if all revision 
ranges got applied? I'm thinking of a situation where the same line got 
changed multiple times over multiple ranges, and the last change would 
render the file so that no conflict would occur.
Does it create a conflict which has to be resolved or will that be 
handled 'gracefully'?

> Requirements:
> 
> - Allow merge conflicts to be resolved during application of a merge.
> 
> - Allow as much automatic merging to be performed as possible without
> requiring human interaction.
> 
> - Allow declarative conflict resolution to avoid any human interaction
> (e.g. --resolve-conflict-using=[older|theirs|mine]), supporting some
> degree of conflict resolution from merges (e.g. build automation).
> 
> - Maintain compatibility with the diff3 command.
> 
> - Allow for resolution more types of conflicts (e.g properties,
> obstructions, etc.).

Will it be possible to have it work like before? Without user 
interaction *during* the merge but get conflicted files which must be 
resolved later?
I'm thinking of situations with flaky network connections, where a user 
might want to do the merging in one step without interruption, and then 
do the resolving later.
In which state of the merge is the callback called? Just to avoid 
timeout errors when the user takes too long to resolve such a conflict 
during the merge operation.

> Possible implementation:
> 
> Subversion will first attempt a merge via its built-in diff library,
> or the diff3 command specified in its config file (or via the
> --diff3-cmd option, for the command-line client).  If a merge conflict
> occurs to either content (file or directory) or properties, it will
> invoke a merge conflict resolution callback provided via its
> svn_client_ctx_t structure (we may provide a default implementation of
> this which calls out to an external binary a la the diff3 command used
> in the original merge).  This callback would prompt the user to
> resolve the conflict (when in non-interactive mode), and upon
                                 ^^^
:)

> resolution allow subsequent merge of revision ranges to occur into the
> same file (important for Subversion's Merge Tracking support).  For
> the command-line client, the callback would throw up a prompt
> something like:
> 
>   Merge conflict detected for "foo.c" at line 37
>   mine:
>    struct iovec vec;
>   theirs:
>    int k;
>   older:
>    int i;
>   Retain (m)ine, (t)hiers, or (o)lder version? _

I suggest to include the line numbers there. Otherwise it may be hard 
for the user to find out where exactly in the files that context is.

> Question for IDE developers:
> 
> I'm really curious how IDEs handle this situation today.  Taking
> TortoiseSVN as an example, I've heard that its TortoiseMerge diff3
> program is great for conflict resolution (though currently lacking an
> edit mode), but not so great for performing merges of a large number
> of changes (e.g. merging changes from trunk into a feature branch),
> especially when the majority of those changes can be applied
> automaticaly with no merge conflicts (and thus don't need typically
> need a merge GUI).  Is this an issue for TortoiseSVN/TortoiseMerge
> today, or am I out of date?  How about for other IDE developers?  How
> do you guys handle this today?  ;-)

If the callback provides the information so that the UI merge tools can 
use whole files, this will work ok. If however the callback only 
provides the context of the file where the conflict occurs, we'd have to 
write a custom merge tool just for this purpose - which is maybe not 
such a bad idea anyway.

[copied from other mail]
 > I'm assuming that the callback will take care of doing the actual
 > merge, and that Subversion libraries will handle the WC meta data
 > manipulation.  Here's the API I've integrated in the tree delta editor
 > (from libsvn_client/repos_diff.c); I may actually want to push this
 > deeper, down into the WC's editor:

Is the Subversion internal diff3 called first and this callback only 
called if there is a conflict?

 > /** A callback used for resolving merge conflicts to content or
 >  * properties encountered during the application of a tree delta to a
 >  * working copy.
 >  *
 >  * This callback is only invoked when not in "dry run" mode.  It
 >  * provides for a smooth balance of automated merging via a
 >  * non-interactive diff3 mechanism like Subversion's internal
 >  * implementation (or an external tool like GNU diff specified via @c
 >  * SVN_CONFIG_OPTION_DIFF3_CMD), and declarative or interactive merge
 >  * conflict resolution (e.g via an external tool like TortoiseMerge or
 >  * Araxis Merge).
 >  *
 >  * If @a content_state and/or @a prop_state are not @c NULL, and the
 >  * conflict is resolved during the callback, set @a content_state
 >  * and/or @a prop_state appropriately (e.g. likely to @c
 >  * svn_wc_notify_state_merged); housekeeping for the resolution of @a
 >  * path will occur automatically.  If @a content_state and/or @a
 >  * prop_state are not @c NULL but returned unchanged, it's assumed
 >  * that the conflict has not been resolved.
 >  *
 >  * All allocations should be performed in @a pool.
 >  *
 >  * @a baton is a closure object; it should be provided by the
 > implementation,
 >  * and passed by the caller.
 >  *
 >  * @since New in 1.5.
 >  */
 > typedef svn_error_t *(*svn_client_conflict_resolver_func_t)
 >   (const char *path,
 >    svn_wc_notify_state_t *content_state,
 >    svn_wc_notify_state_t *prop_state,
 >    svn_boolean_t dry_run,
 >    void *baton,
 >    apr_pool_t *pool);

I see that this callback only has one 'path' parameter. I don't see 
where the information would be to actually do a merge? Doesn't a merge 
require at least three files/paths to actually get a conflict which must 
be resolved?


Some other thoughts:
* sometimes it's not possible to resolve a conflict without modifying 
also other files (not just the one which has the conflict). Will it be 
possible for the UI merge tool to just tell "sorry, can't resolve this" 
and Subversion will then behave as before and leave the file conflicted?
* it would be nice if the svn:mime-type property value also is passed to 
the callback: UI tools could use this information to find out what the 
best way would be to resolve a conflict or just to simply adjust the UI 
according to the mime type
* if the callback does not provide only the context where the conflict 
occurs but whole files, an information is required where Subversion can 
not resolve the conflict itself: UI merge tools may use a different 
diff3 algorithm which won't see a conflict where Subversion sees one. 
Maybe the line numbers of where the conflict is supposed to be.

Stefan

-- 
        ___
   oo  // \\      "De Chelonian Mobile"
  (_,\/ \_/ \     TortoiseSVN
    \ \_/_\_/>    The coolest Interface to (Sub)Version Control
    /_/   \_\     http://tortoisesvn.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: Merge conflict resolution

Posted by Daniel Rall <dl...@collab.net>.
On Wed, 22 Nov 2006, Martin Hauner wrote:
...
> Daniel Rall <dl...@collab.net> wrote:
...
> > While conflict markers might not currently seem like much of a problem
> > to most people (at least, to those not grumbling that Subversion is
> > "corrupting their files"), Merge Tracking really complicates things.
> > In today's Subversion, we apply only one revision range during any
> > merge operation.  With Merge Tracking, we may apply multiple revision
> > ranges during a single merge operation, a rather fundamental
> > difference with many ramifications.  Once a file has a merge conflict,
> > we have to stop applying revision ranges, meaning that we might apply
> > only a portion of the revisions requested for merge by the user.
> > Improved merge conflict resolution handling will really help address
> > this user experience.
> 
> Currently if there is a merge conflict, we have four files: the file
> with conflict markers, conflict_old, conflict_wrk and conflict_new.
> I think the standard (gui) way is to launch a 3 way merge with the 3
> conflict files, completely ignoring the file with the conflict markers.

Yup!

> I would expect that the (non interactive) merge procedure will not
> change.

Some tools (e.g. ClearCase) allow you to specify which version to use
(old/working/new) to automatically perform non-interactive merging.
Apparently this is popular with SCM build automation.

The callback I'm suggesting would allow this type of thing to be
implemented (meaning one could theoretically change the
non-interactive merge process).

> If merge tracking allows multiple conflicts with differnt merge
> ranges svn should stop after the first conflict and write the four
> files like now.

This was my initial reaction, too.  However, that's a rather major
departure from the current semantics of 'svn merge' (which now always
attempts to merge all requested revisions), and not particularly user
friendly for the merge to simply stop part way through...

> ... It should store any unmerged range, whatever infomration is
> required to restart the merge later with the next revision
> range. Merging of this file stops here for now.
>
> When the user "svn resolved" the first conflict, svn should take the
> stored information to continue the merge. If no other conflict shows
> up, fine.  If another conflict shows up, stop and restart again
> after the user also resolved this conflict.

I think we actually have to stop applying any more revision ranges
after a conflict occurs (not just to that file), since there may be
directories or obstructions involved which subsequent merges depend
on.

Your idea of storing some state about the requested-but-unmerged
revision ranges and supplying some mechanism to restart the merge is
interesting!  ('svn resolved' wouldn't be the correct place, though.)
We could output a message indicating that only a partial merge
occurred, and then allow some sub-command (e.g. 'svn merge --restart')
to continue the merge after conflicts had been resolved in the
traditional manner.

If we go this direction, we'd punt on the merge resolution callback
idea.  Which do y'all think is more user friendly?

> > Requirements:
> > 
> > - Allow merge conflicts to be resolved during application of a merge.
> 
> I think the best would be to have both: interactive and non-interactive
> merge. This should simply be an option to the merge command.

There's already a global --non-interactive flag on the 'svn'
command-line client.  We'd pass the equivalent of this information
along to allow a merge resolution callback to DTRT.

> > - Allow as much automatic merging to be performed as possible without
> > requiring human interaction.
> > 
> > - Allow declarative conflict resolution to avoid any human interaction
> > (e.g. --resolve-conflict-using=[older|theirs|mine]), supporting some
> > degree of conflict resolution from merges (e.g. build automation).
> > 
> > - Maintain compatibility with the diff3 command.
> > 
> > - Allow for resolution more types of conflicts (e.g properties,
> > obstructions, etc.).
...
> > I'm really curious how IDEs handle this situation today.  Taking
> > TortoiseSVN as an example, I've heard that its TortoiseMerge diff3
> > program is great for conflict resolution (though currently lacking an
> > edit mode), but not so great for performing merges of a large number
> > of changes (e.g. merging changes from trunk into a feature branch),
> > especially when the majority of those changes can be applied
> > automaticaly with no merge conflicts (and thus don't need typically
> > need a merge GUI).  Is this an issue for TortoiseSVN/TortoiseMerge
> > today, or am I out of date?  How about for other IDE developers?  How
> > do you guys handle this today?  ;-)
> 
> Thanks for asking.. :)

You're welcome!  :)

> In earlier versions I changed svn's diff command settings (I think that
> was for diff only). That was very awkward to use. Not really usable to
> run a graphical diff tool. There were a couple of problems. I can't
> remember exactly what the problems were but for that reason I "copied"
> part of svns diff code to have proper control over the way the diff
> tool is started. I didn't try to run a visual merge this way.

http://svn.collab.net/repos/svn/trunk/CHANGES shows that there's been
numerous problems with the custom diff3 command over the years, and
invoking a GUI diff3 for every merge doesn't sound particularly
enticing, either.

> For merge I simply call the merge api like the svn client. Subversion
> does all the work and provides the three conflict files for each file
> with a conflict. After the complete merge is done I can run
> "edit conflict" (from the gui status view) on each conflicted file to
> bring up the merge tool with the three conflict files.

Gotcha, thanks for the description.

It sounds like everyone is clear now on how the merge-tracking
branch's multi-revision range merge implementation will affect
merging and conflict resolution.

Re: Merge conflict resolution

Posted by Martin Hauner <Ma...@gmx.net>.
Hi,

Daniel Rall <dl...@collab.net> wrote:
> Hello Subversion IDE developers.  I'm currently working on building
> Merge Tracking support for Subversion.  As part of this journey, I've
> discovered that writing merge conflict markers into a file isn't
> conducive to a friendly user experience when applying multiple
> revision ranges during a single merge operation (or otherwise, for
> that matter :).  I need to allow for a better way of handling merge
> conflict resolution in Subversion, and I'd like your help in assuring
> that this is designed from the ground up with Subversion IDEs in mind.
> 
> 
> Background:
> 
> While conflict markers might not currently seem like much of a problem
> to most people (at least, to those not grumbling that Subversion is
> "corrupting their files"), Merge Tracking really complicates things.
> In today's Subversion, we apply only one revision range during any
> merge operation.  With Merge Tracking, we may apply multiple revision
> ranges during a single merge operation, a rather fundamental
> difference with many ramifications.  Once a file has a merge conflict,
> we have to stop applying revision ranges, meaning that we might apply
> only a portion of the revisions requested for merge by the user.
> Improved merge conflict resolution handling will really help address
> this user experience.

Currently if there is a merge conflict, we have four files: the file
with conflict markers, conflict_old, conflict_wrk and conflict_new.
I think the standard (gui) way is to launch a 3 way merge with the 3
conflict files, completely ignoring the file with the conflict markers.

I would expect that the (non interactive) merge procedure will not change.

If merge tracking allows multiple conflicts with differnt merge ranges
svn should stop after the first conflict and write the four files like
now. It should store any unmerged range, whatever infomration is required
to restart the merge later with the next revision range. Merging of this
file stops here for now.

When the user "svn resolved" the first conflict, svn should take the stored
information to continue the merge. If no other conflict shows up, fine.
If another conflict shows up, stop and restart again after the user also 
resolved this conflict.


> Requirements:
> 
> - Allow merge conflicts to be resolved during application of a merge.

I think the best would be to have both: interactive and non-interactive
merge. This should simply be an option to the merge command.

> - Allow as much automatic merging to be performed as possible without
> requiring human interaction.
> 
> - Allow declarative conflict resolution to avoid any human interaction
> (e.g. --resolve-conflict-using=[older|theirs|mine]), supporting some
> degree of conflict resolution from merges (e.g. build automation).
> 
> - Maintain compatibility with the diff3 command.
> 
> - Allow for resolution more types of conflicts (e.g properties,
> obstructions, etc.).
> 
> 
> Possible implementation:
> [..]

> Question for IDE developers:
> 
> I'm really curious how IDEs handle this situation today.  Taking
> TortoiseSVN as an example, I've heard that its TortoiseMerge diff3
> program is great for conflict resolution (though currently lacking an
> edit mode), but not so great for performing merges of a large number
> of changes (e.g. merging changes from trunk into a feature branch),
> especially when the majority of those changes can be applied
> automaticaly with no merge conflicts (and thus don't need typically
> need a merge GUI).  Is this an issue for TortoiseSVN/TortoiseMerge
> today, or am I out of date?  How about for other IDE developers?  How
> do you guys handle this today?  ;-)

Thanks for asking.. :)

In earlier versions I changed svn's diff command settings (I think that
was for diff only). That was very awkward to use. Not really usable to
run a graphical diff tool. There were a couple of problems. I can't
remember exactly what the problems were but for that reason I "copied"
part of svns diff code to have proper control over the way the diff
tool is started. I didn't try to run a visual merge this way.

For merge I simply call the merge api like the svn client. Subversion
does all the work and provides the three conflict files for each file
with a conflict. After the complete merge is done I can run
"edit conflict" (from the gui status view) on each conflicted file to
bring up the merge tool with the three conflict files.

-- 
Martin

Subcommander 1.2.1, http://subcommander.tigris.org
a cross platform Win32/Unix/MacOSX subversion gui client & diff/merge tool.



"Ein Herz für Kinder" - Ihre Spende hilft! Aktion: www.deutschlandsegelt.de
Unser Dankeschön: Ihr Name auf dem Segel der 1. deutschen America's Cup-Yacht!

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: Merge conflict resolution

Posted by Daniel Rall <dl...@collab.net>.
On Tue, 21 Nov 2006, Mark Phippard wrote:
...
> >>In Subclipse when you choose to Edit Conflicts we take the 3 files
> >>and feed them to the Eclipse merge editor.  There is a button to
> >>merge all non-conflicting changes, but the user has to use it or
> >>walk through every change, not just the conflicts.  I often just
> >>open the marked up file in an editor and fix it myself.
> >
> >Ah!  This sounds similar to the situation I'm guessing arises with
> >TortoiseMerge (as described above).  Does this mean that Subclipse
> >could also benefit from a merge conflict resolution callback, allowing
> >Subversion to handle the obvious merging, and opening up the Eclipse
> >3-way merge tool for only the conflicts?  Or do I misunderstand?
>
> I don't know.  If in the end we still just feed the merge tool the
> same 3 revisions, it is going to give the same results.

Yes.  The benefit that I am hoping to achieve is to avoid spawning a
GUI merge tool for files which can be merged automatically via
Subversion's built-in diff3 library, but spawn a GUI merge tool
*during the merge* as-needed for files which require manual
intervention to merge.

Does Subclipse already work in a similar fashion?  Perhaps the merge
is automated, but you come back and manually resolve the conflicts
using the GUI merge tool?

> I guess the improvement would be if there was a 4th revision where
> the stuff that could be merged was, and the conflicts still looked
> like the base revision.  Then the merge tool would likely only have
> the conflicts.  We cannot do this today because the marked up
> revision would not work in the merge tool.

Right.  While this was not part of what I was originally proposing,
it's certainly an interesting idea.  I think we should file this as an
enhancment.

Re: Merge conflict resolution

Posted by Mark Phippard <ma...@gmail.com>.
Daniel Rall wrote:
>> What if the user wants something like "mine before theirs"?  In
>> other words, both?
>>     
>
> With a 3-way merge tool like the one provided by Eclipse, I'm assuming
> mixing changes on a line-by-ine basis (and probably even editing in
> place) is no problem.
>   
Yes, Eclipse merge editor is OK in this regard and getting better.

>> In Subclipse when you choose to Edit Conflicts we take the 3 files
>> and feed them to the Eclipse merge editor.  There is a button to
>> merge all non-conflicting changes, but the user has to use it or
>> walk through every change, not just the conflicts.  I often just
>> open the marked up file in an editor and fix it myself.
>>     
>
> Ah!  This sounds similar to the situation I'm guessing arises with
> TortoiseMerge (as described above).  Does this mean that Subclipse
> could also benefit from a merge conflict resolution callback, allowing
> Subversion to handle the obvious merging, and opening up the Eclipse
> 3-way merge tool for only the conflicts?  Or do I misunderstand?
>
>   
I don't know.  If in the end we still just feed the merge tool the same 
3 revisions, it is going to give the same results.  I guess the 
improvement would be if there was a 4th revision where the stuff that 
could be merged was, and the conflicts still looked like the base 
revision.  Then the merge tool would likely only have the conflicts.   
We cannot do this today because the marked up revision would not work in 
the merge tool.


Mark

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: Merge conflict resolution

Posted by Daniel Rall <dl...@collab.net>.
Thanks for the response, Mark!  Comments inline below.

On Tue, 21 Nov 2006, Mark Phippard wrote:

> Daniel Rall wrote:
> >Possible implementation:
> >
> >Subversion will first attempt a merge via its built-in diff library,
> >or the diff3 command specified in its config file (or via the
> >--diff3-cmd option, for the command-line client).  If a merge conflict
> >occurs to either content (file or directory) or properties, it will
> >invoke a merge conflict resolution callback provided via its
> >svn_client_ctx_t structure (we may provide a default implementation of
> >this which calls out to an external binary a la the diff3 command used
> >in the original merge).  This callback would prompt the user to
> >resolve the conflict (when in non-interactive mode), and upon
> >resolution allow subsequent merge of revision ranges to occur into the
> >same file (important for Subversion's Merge Tracking support).  For
> >the command-line client, the callback would throw up a prompt
> >something like:
> >
> >  Merge conflict detected for "foo.c" at line 37
> >  mine:
> >   struct iovec vec;
> >  theirs:
> >   int k;
> >  older:
> >   int i;
> >  Retain (m)ine, (t)hiers, or (o)lder version? _
> >
> >IDEs could obviously do something even more user-friendly, throwing up
> >a three-way merge GUI like TortoiseMerge, WinMerge, Araxis Merge,
> >etc., but ONLY when a merge conflict actually occurs.
>
> I assume what you are saying is that the callback would occur on the 
> conflict, not at the end of the process.

I'm envisioning the conflict resolution callback being invoked after
merging of an individual revision range (e.g. "-r 3:7") occurs into a
single file, but before merging of any changes from that revision
range to any other files affected by application of the patch.

> I do not see how a GUI tool could handle this well, without being
> really custom written for the purpose.  The GUI editors you mention
> all want to deal with entire files, not sections.  I almost think a
> GUI would have to be custom and be somewhat like what you provide
> for the command line.  Perhaps being a GUI, it could show some more
> file context.  Hard to say.  In Subclipse we are using the 3-way
> merge editor provided by Eclipse, I do not know if it has any way to
> be driven like this.

I'm assuming that GUI merge tools would deal with conflicts on a
file-by-file basis.  The section-by-section example I showed above
would be a custom implementation of this conflict resolution callback
specific to the command-line client, which would take a file in
conflict and ask you to resolve a section at a time via the prompts I
described above.

I'm betting the 3-way merge editor provided by Eclipse will handle
this file-by-file merge just fine.

> What responsiblity will the callback function have?  Will it just be to 
> return a code of some sort that tells you which revision to take?

I'm assuming that the callback will take care of doing the actual
merge, and that Subversion libraries will handle the WC meta data
manipulation.  Here's the API I've integrated in the tree delta editor
(from libsvn_client/repos_diff.c); I may actually want to push this
deeper, down into the WC's editor:

/** A callback used for resolving merge conflicts to content or
 * properties encountered during the application of a tree delta to a
 * working copy.
 *
 * This callback is only invoked when not in "dry run" mode.  It
 * provides for a smooth balance of automated merging via a
 * non-interactive diff3 mechanism like Subversion's internal
 * implementation (or an external tool like GNU diff specified via @c
 * SVN_CONFIG_OPTION_DIFF3_CMD), and declarative or interactive merge
 * conflict resolution (e.g via an external tool like TortoiseMerge or
 * Araxis Merge).
 *
 * If @a content_state and/or @a prop_state are not @c NULL, and the
 * conflict is resolved during the callback, set @a content_state
 * and/or @a prop_state appropriately (e.g. likely to @c
 * svn_wc_notify_state_merged); housekeeping for the resolution of @a
 * path will occur automatically.  If @a content_state and/or @a
 * prop_state are not @c NULL but returned unchanged, it's assumed
 * that the conflict has not been resolved.
 *
 * All allocations should be performed in @a pool.
 *
 * @a baton is a closure object; it should be provided by the implementation,
 * and passed by the caller.
 *
 * @since New in 1.5.
 */
typedef svn_error_t *(*svn_client_conflict_resolver_func_t)
  (const char *path,
   svn_wc_notify_state_t *content_state,
   svn_wc_notify_state_t *prop_state,
   svn_boolean_t dry_run,
   void *baton,
   apr_pool_t *pool);


> What if the user wants something like "mine before theirs"?  In
> other words, both?

With a 3-way merge tool like the one provided by Eclipse, I'm assuming
mixing changes on a line-by-ine basis (and probably even editing in
place) is no problem.

With the command-line client, you'd do something like you'd do today
(and open up the file in your editor).

> >Question for IDE developers:
> >
> >I'm really curious how IDEs handle this situation today.  Taking
> >TortoiseSVN as an example, I've heard that its TortoiseMerge diff3
> >program is great for conflict resolution (though currently lacking an
> >edit mode), but not so great for performing merges of a large number
> >of changes (e.g. merging changes from trunk into a feature branch),
> >especially when the majority of those changes can be applied
> >automaticaly with no merge conflicts (and thus don't need typically
> >need a merge GUI).  Is this an issue for TortoiseSVN/TortoiseMerge
> >today, or am I out of date?  How about for other IDE developers?  How
> >do you guys handle this today?  ;-)
>
> In Subclipse when you choose to Edit Conflicts we take the 3 files
> and feed them to the Eclipse merge editor.  There is a button to
> merge all non-conflicting changes, but the user has to use it or
> walk through every change, not just the conflicts.  I often just
> open the marked up file in an editor and fix it myself.

Ah!  This sounds similar to the situation I'm guessing arises with
TortoiseMerge (as described above).  Does this mean that Subclipse
could also benefit from a merge conflict resolution callback, allowing
Subversion to handle the obvious merging, and opening up the Eclipse
3-way merge tool for only the conflicts?  Or do I misunderstand?

- Dan

Re: Merge conflict resolution

Posted by Mark Phippard <ma...@gmail.com>.
Daniel Rall wrote:
> Possible implementation:
>
> Subversion will first attempt a merge via its built-in diff library,
> or the diff3 command specified in its config file (or via the
> --diff3-cmd option, for the command-line client).  If a merge conflict
> occurs to either content (file or directory) or properties, it will
> invoke a merge conflict resolution callback provided via its
> svn_client_ctx_t structure (we may provide a default implementation of
> this which calls out to an external binary a la the diff3 command used
> in the original merge).  This callback would prompt the user to
> resolve the conflict (when in non-interactive mode), and upon
> resolution allow subsequent merge of revision ranges to occur into the
> same file (important for Subversion's Merge Tracking support).  For
> the command-line client, the callback would throw up a prompt
> something like:
>
>   Merge conflict detected for "foo.c" at line 37
>   mine:
>    struct iovec vec;
>   theirs:
>    int k;
>   older:
>    int i;
>   Retain (m)ine, (t)hiers, or (o)lder version? _
>
> IDEs could obviously do something even more user-friendly, throwing up
> a three-way merge GUI like TortoiseMerge, WinMerge, Araxis Merge,
> etc., but ONLY when a merge conflict actually occurs.
>   
I assume what you are saying is that the callback would occur on the 
conflict, not at the end of the process.  I do not see how a GUI tool 
could handle this well, without being really custom written for the 
purpose.  The GUI editors you mention all want to deal with entire 
files, not sections.  I almost think a GUI would have to be custom and 
be somewhat like what you provide for the command line.  Perhaps being a 
GUI, it could show some more file context.  Hard to say.  In Subclipse 
we are using the 3-way merge editor provided by Eclipse, I do not know 
if it has any way to be driven like this.

What responsiblity will the callback function have?  Will it just be to 
return a code of some sort that tells you which revision to take?  What 
if the user wants something like "mine before theirs"?  In other words, 
both?


> Question for IDE developers:
>
> I'm really curious how IDEs handle this situation today.  Taking
> TortoiseSVN as an example, I've heard that its TortoiseMerge diff3
> program is great for conflict resolution (though currently lacking an
> edit mode), but not so great for performing merges of a large number
> of changes (e.g. merging changes from trunk into a feature branch),
> especially when the majority of those changes can be applied
> automaticaly with no merge conflicts (and thus don't need typically
> need a merge GUI).  Is this an issue for TortoiseSVN/TortoiseMerge
> today, or am I out of date?  How about for other IDE developers?  How
> do you guys handle this today?  ;-)
>   
In Subclipse when you choose to Edit Conflicts we take the 3 files and 
feed them to the Eclipse merge editor.  There is a button to merge all 
non-conflicting changes, but the user has to use it or walk through 
every change, not just the conflicts.  I often just open the marked up 
file in an editor and fix it myself.

Mark

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org