You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@subversion.apache.org by Philip Martin <ph...@wandisco.com> on 2012/07/02 10:41:16 UTC

Re: bug in "Undoing Changes" functionality of merge -c -N?

Nairn Baliber <pl...@gmail.com> writes:

> This creates a conflict (upon running that command, not on commit), whereby
> the merge-left file contains everything up until line r4, and the
> merge-right file contains everything up until line r3. In other words,
> instead of removing a past change, the command seems to want to revert the
> entire file back to either revision 3 or 4, removing changes in subsequent
> revisions (5 and 6, in this case).

The left and right files are simply the r3 and r4 files and the
difference is a line added at the end of the file.  The merge attempts
to remove the line from the current file where the line is no longer at
the end.  Subversion's merge algorithm detects that the context
following the line in the current file has no match in the original file
and flags a conflict.  A more permissive algoithm would ignore the
conflict and allow the merge.  That's a better result in some cases but
it may well be a worse result in other cases.

You can configure Subversion to use an external diff3/merge tool.
kdiff3 has a more permissive algorithm that allows the merge without a
conflict.

-- 
Philip

Re: bug in "Undoing Changes" functionality of merge -c -N?

Posted by Johan Corveleyn <jc...@gmail.com>.
On Tue, Jul 3, 2012 at 1:26 AM, Nairn Baliber <pl...@gmail.com> wrote:
> Hi Phillip.
>
> Thanks for the response.
>
> I am unclear about the intended functionality of SVN when using merge -c -M
> (or -r M:<M-1>), given your response and the instructions in the svn book.
> If I display the conflict brought up by the aforementioned merge command,
>
> svn merge -c -4 file:///path_to_repos/trunk,
>
> it reads as follows:
>
> ------
> this is an edit of testcode.py.  r2.
>
>
> this is another edit of testcode.py.  r3.
> <<<<<<< MINE (select with 'mc') (6,6)
>
> this is an edit of testcode.py.  will get rid of this one.  r4.
>
>
> another edit of testcode.py.  keeping it.  r5.
>
> yet another edit of testcode.py.  also keeping it.  r6.
> ||||||| ORIGINAL (6,2)
>
> this is an edit of testcode.py.  will get rid of this one.  r4.
> =======
>>>>>>>> THEIRS (select with 'tc') (6,0)
> ------
>
> There is no choice for built-in conflict resolution that delivers the result
> claimed in the svn book for "Undoing Changes."  That is, neither resolved
> (r), mine-conflict (mc), theirs-conflict (tc), mine-full (mf), nor
> theirs-full (tf) will create a file with all lines of the working copy
> intact except for the one ending in r4.  Therefore, I'm not sure how a "more
> permissive" algorithm could be a solution.  The built-in choices for
> conflict resolution (barring visual inspection and editing by the user) are
> 1) keep the file as it was before the merge attempt,
> 2)revert the file to r3, or
> 3)revert the file to r4.
>
> The only way to produce the claimed functionality of undoing past changes in
> this simple case is to visually inspect the displayed conflict using the dc
> command (it is not at all obvious how to find the differences by postponing
> and inspecting the resulting files, even in the ideal simple case I am
> testing), edit the working copy to produce the desired result, and commit.
>
> In this very simple case, that is not very difficult.  In real-life
> situations, it would be at best extremely burdensome, and very prone to user
> error.  This doesn't seem to me to be the intended, and isn't anything like
> the use case described in the svn book.
>
> If, however, this is the way SVN expects merge -c -M to be used to undo past
> "bad" changes to files in a repository, then the intention is not properly
> represented in the svn book.  There should be a clear statement, in that
> case, that the **only** case in which merge -c -M is useful is if all
> changes committed in revision M were made at the end of the file or files
> being committed.  In real-world use cases, it would be just as easy if not
> easier to svn cat or diff the files before and after the offending commit,
> find the differences that way (with less clutter than appears in with the dc
> command), and edit the working copy by hand to reverse the changes.
>
> But again, since you mentioned using a tool with a more permissive algorithm
> to "allow a merge without a conflict," it sounds as though one of the
> potential outcomes of the conflict raised by SVN should be a file with line
> r4 having been removed.  If that's not the case and everything is
> functioning as designed, please let me know.  I would again stress that if
> that is the case, the instructions on the topic should be changed.  In fact,
> the whole "Undoing Changes" section of the svn book could be removed
> entirely.

I'd like to point out that your example is really an edge case: where
the lines immediately around the to-be-undone 'r4-line' (its context)
have been changed since r4. Usually this is not the case, and the
reverse 'r4' can be applied without problems. I've used the
reverse-merge feature a couple of times, and never ran into conflicts.
So the example from the book is still valid, it covers 99% of
real-world cases IMHO.

For your case, you can think of it this way: 'merge -c -M' first
calculates the diff between M and M-1, and then tries to apply this
diff (similar to what the standard unix 'patch' command does) to your
working copy. The diff between 4 and 3 will look something like this
(try 'svn diff -c -4'):

[[[
C:\Temp\svntest\wc\trunk>svn diff -c -4 test.txt
Index: test.txt
===================================================================
--- test.txt    (revision 4)
+++ test.txt    (revision 3)
@@ -1,4 +1,3 @@
 this is my first import to trunk. r1.
 this is my first commit, first edit of testcode.py. r2.
 this is another edit of testcode.py. r3.
-this is an edit of testcode.py. i'll get rid of this one. r4.
]]]

As you can see, there are no context lines after line 4. Now when svn
tries to apply this diff to your working copy, it will try to match
line 4 to know which line to remove. But now it finds a non-empty
context after line 4, i.e. the context doesn't match. So svn gives a
conflict because it is (perhaps too) careful not to mess things up for
you. Other merge/diff/patch algorithms may be more tolerant, and allow
context lines to differ ...

-- 
Johan

Re: bug in "Undoing Changes" functionality of merge -c -N?

Posted by Nairn Baliber <pl...@gmail.com>.
Hi Phillip.

Thanks for the response.

I am unclear about the intended functionality of SVN when using merge -c -M
(or -r M:<M-1>), given your response and the instructions in the svn book.
If I display the conflict brought up by the aforementioned merge command,

svn merge -c -4 file:///path_to_repos/trunk,

it reads as follows:

------
this is an edit of testcode.py.  r2.

this is another edit of testcode.py.  r3.
<<<<<<< MINE (select with 'mc') (6,6)

this is an edit of testcode.py.  will get rid of this one.  r4.

another edit of testcode.py.  keeping it.  r5.

yet another edit of testcode.py.  also keeping it.  r6.
||||||| ORIGINAL (6,2)

this is an edit of testcode.py.  will get rid of this one.  r4.
=======
>>>>>>> THEIRS (select with 'tc') (6,0)
------

There is no choice for built-in conflict resolution that delivers the
result claimed in the svn book for "Undoing Changes."  That is, neither
resolved (r), mine-conflict (mc), theirs-conflict (tc), mine-full (mf), nor
theirs-full (tf) will create a file with all lines of the working copy
intact except for the one ending in r4.  Therefore, I'm not sure how a
"more permissive" algorithm could be a solution.  The built-in choices for
conflict resolution (barring visual inspection and editing by the user) are
1) keep the file as it was before the merge attempt,
2)revert the file to r3, or
3)revert the file to r4.

The only way to produce the claimed functionality of undoing past changes
in this simple case is to visually inspect the displayed conflict using the
dc command (it is not at all obvious how to find the differences by
postponing and inspecting the resulting files, even in the ideal simple
case I am testing), edit the working copy to produce the desired result,
and commit.

In this very simple case, that is not very difficult.  In real-life
situations, it would be at best extremely burdensome, and very prone to
user error.  This doesn't seem to me to be the intended, and isn't anything
like the use case described in the svn book.

If, however, this is the way SVN expects merge -c -M to be used to undo
past "bad" changes to files in a repository, then the intention is not
properly represented in the svn book.  There should be a clear statement,
in that case, that the **only** case in which merge -c -M is useful is if
all changes committed in revision M were made at the end of the file or
files being committed.  In real-world use cases, it would be just as easy
if not easier to svn cat or diff the files before and after the offending
commit, find the differences that way (with less clutter than appears in
with the dc command), and edit the working copy by hand to reverse the
changes.

But again, since you mentioned using a tool with a more permissive
algorithm to "allow a merge without a conflict," it sounds as though one of
the potential outcomes of the conflict raised by SVN should be a file with
line r4 having been removed.  If that's not the case and everything is
functioning as designed, please let me know.  I would again stress that if
that is the case, the instructions on the topic should be changed.  In
fact, the whole "Undoing Changes" section of the svn book could be removed
entirely.

Thanks again for your time.

Nairn


On Mon, Jul 2, 2012 at 1:41 AM, Philip Martin <ph...@wandisco.com>wrote:

> Nairn Baliber <pl...@gmail.com> writes:
>
> > This creates a conflict (upon running that command, not on commit),
> whereby
> > the merge-left file contains everything up until line r4, and the
> > merge-right file contains everything up until line r3. In other words,
> > instead of removing a past change, the command seems to want to revert
> the
> > entire file back to either revision 3 or 4, removing changes in
> subsequent
> > revisions (5 and 6, in this case).
>
> The left and right files are simply the r3 and r4 files and the
> difference is a line added at the end of the file.  The merge attempts
> to remove the line from the current file where the line is no longer at
> the end.  Subversion's merge algorithm detects that the context
> following the line in the current file has no match in the original file
> and flags a conflict.  A more permissive algoithm would ignore the
> conflict and allow the merge.  That's a better result in some cases but
> it may well be a worse result in other cases.
>
> You can configure Subversion to use an external diff3/merge tool.
> kdiff3 has a more permissive algorithm that allows the merge without a
> conflict.
>
> --
> Philip
>