[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: An analysis of possible tree conflicts during update

From: Julian Foad <julianfoad_at_btopenworld.com>
Date: Wed, 02 Dec 2009 12:57:31 +0000

Stefan Sperling wrote:
> On Wed, Dec 02, 2009 at 08:53:00AM +0100, Daniel Näslund wrote:
> > Intro
> > ======
> > This thread was basically about me trying to convince myself that
> > the approach in notes/tree-conflicts/resolution.txt holds. Here's an
> > attempt to describe the state the WC is in during the different "file
> > update tree conflicts".

Excellent, I'm glad you're doing this. "resolution.txt" is thoughts from
a year ago. If you can update those thoughts or make them more
consistent or mark which ones are done in 1.6.x and which are not, any
of those contributions would be very useful.

> > [[[
> > * When "svn update" or "svn switch" raises a tree conflict, it shall update
> > the victim's "base" version from OLD to THEIRS, and leave the "working"
> > version in a state that would be committable (but for the explicit check
> > that prevents committing an item marked as in conflict) and that, if
> > committed, would restore the item to how it looked in "mine". This may
> > involve changing the scheduling of the item, e.g. to be re-added if "update"
> > applied a delete.
> > ]]]
> >
> > Does the tree conflict code do that?
>
> Yes it does, at least in the following case:
>
> If the update tries to delete a locally modified file, the file in
> working is schedule for re-add.
> $ svn st
> M alpha
> $ svn up
> C alpha
> At revision 3.
> Summary of conflicts:
> Tree conflicts: 1
> $ svn st alpha
> A + C alpha
> > local edit, incoming delete upon update
> $ svn info alpha | grep Copied
> Copied From URL: file:///tmp/svn-sandbox/repos/trunk/alpha
> Copied From Rev: 2
>
>
> > When running my test cases I could
> > just use 'svn resolved <file>' but I may have missed some edge cases.
>
> In the above case you can use 'svn resolved alpha' to keep alpha.
> You'd have to use 'svn revert alpha' to get rid of alpha.
>
> > A bit early but I was wondering about this piece from resolution.txt:
> >
> > [[[
> > "Options" lists resolution options that ought to be available. The
> > resolution options "THEIRS" and "MINE" should be available in every case (so
> > that a user can resolve a whole tree at once with one of those options) and
> > should be implemented internally. Any other options listed here may be
> > recipes for the user to apply manually. These recipes are starting from the
> > state in which the WC should be left by Subversion after raising a conflict.
> > ]]]
> >
> > Is this still the way we want it? THEIRS and MINE is handled in our
> > code, the other options is text that explains what to do and leaves it
> > to the user to do it?
>
> I guess this is just about keeping possible other options in mind.
> I'm not sure if we can always guess a suitable resolution, it really
> depends on the situation.
> Does the text even give examples for what the other options might be?

What I meant was that, in this file "resolution.txt", I listed other
possibilities for resolutions that might be useful, and we can document
those somewhere (on a web site) for users to follow manually (e.g. "copy
X to Y, revert X, apply the patch you saved in step 1").

We can also provide interactive menu options for making svn do some of
those things, if we want to.

I didn't mean we should provide interactive menu options that just print
a list of instructions.

> Let's keep it simple. Make the resolver deal with the simple cases,
> because right now, usability sucks even in the simple cases.
> If we did make the resolution callback provide 'theirs' and 'mine'
> options with auto-resolution in *all* file cases, we'd be pretty good.
> Note that this will get very difficult when dealing with directories,
> at least in the 1.6.x (and possibly 1.7.x) world.

Yup.

> What should definitely be there is a 'postpone' option, meaning "leave
> the conflict markers in place and leave the WC in this state, I'll deal
> with it manually". But I don't think the option needs to explain anything
> or suggest ways to go about solving the conflict. What if we get it
> wrong and give wrong advice? Users won't be happy. We'll have to rely
> on them to engage their brain instead.

Yup. (Though "What if we get it wrong" is a dubious argument.)

> We might also want to provide an option to view the revision log of
> any file or its parent directory from within the menu, so people can
> dig in the history without having to open another terminal etc.

Heh, sure we could, and we could make the log history navigable and ...
but that's more of a UI task that TortoiseSvn and RapidSvn and VisualSvn
can do well, and svn can never do well.

> > Categories of conflicts
> > ========================
> > 1. Locale add, incoming add
> > 2. Locale del, incoming del
> > 3. Locale del, incoming edit
> > 4. Locale edit, incoming del

It's also worth thinking about moves as different from delete-and-add,
although we are not yet ready to detect them properly.

> s/Locale/Local/g

The English adjective is "local" (pronounced "LOW-kl"). (English
speakers sometimes use the (French?) noun "locale" ("lk-AHL", especially
in i18n/l10n contexts.)

> > 1. Locale add, incoming add
> > ============================
> > Some use cases:
> > - I have already applied the patch - their item is identical to mine.
> > -> want to do it just once -> THEIRS.
>
> ... or MINE, since the item is identical?

Sure, and it would be best if the UI made it clear that the item is
identical so MINE and THEIRS have the same result. I just thought that
THEIRS was in some sense the more logicalm option to suggest: to keep
the copy that was committed first, rather than "replacing" it (in a
no-op sense) with my copy of an identical item.

Note: It would be wrong not to offer MINE and THEIRS as options, even if
we also offer an option named something like
"JUST-KEEP-ONE-COPY-BECAUSE-IT'S-THE-SAME", because the user might be
wanting to choose MINE or THEIRS without caring whether the content is
identical, and should be able to choose those options in every case.

> > - Two different new items happened to be given the same name. ->
> > accept theirs & rename mine -> RENAME-MINE.
>
> What about keeping my name, and renaming the incoming file instead?

Sure, that's a possible alternative. I thought RENAME-MINE was better,
for reasons similar to "THEIRS" above. Do you think RENAME-INCOMING is
more likely to be useful, or useful enough to present as a separate
option?

It depends whether the user is merging "up" or "down" the stability
scale:

  * merging stable changes into a less stable destination
    (svn update, or svn merge from trunk to dev branch, or from release
branch to trunk)

    => default should be to keep THEIRS

or

  * merging less-stable changes into a more-stable branch
    (svn merge to a release branch, or from dev branch to trunk)

    => default should be to keep MINE

The section of "resolution.txt" that we're looking at is the "up/sw"
section, in which I assumed "update" rather than "switch", so "keep
THEIRS" is the preferred resolution.

> This would result in:
> R myfile
> A + theirfile

That's
i
  R|R+|A|A+ myfile
  R+|A+ theirfilenewname

> > - I was doing roughly the same thing but the item is a bit different.
> > -> merge the two items -> manual 2-way merge (or 3-way if both are
> > w/hist and it's the same copy-from source) -> MERGE.
>
> Yeah, we should provide a merge option in that case.
> Much like what update does today for text conflicts, but with support
> for installing the merged file on top of some other file in WORKING.

"Installing the merged file on top of some other file in WORKING"?
What/why?

> Possible options after the merge (based on OpenBSD's sysmerge which
> merges configuration files after a system update):
>
> - edit the merged file again
> - install the merged file in WORKING
> - view a diff between a WORKING file and the merged file
> - view a diff between a BASE file and the merged file
> - re-do the merge
> - view the merged file
> - discard the merged file and go back to previous menu
>
> > THEIRS
> > --------
> > Replace <file> in WORKING with the new BASE that comes in during the
> > update.
> > *Problems*: We may need to undo a local move or copy operation with
> > destination <file>.
>
> Let's ignore existing copies of the file for now.
>
> > MINE
> > -----
> > WORKING-TARGET is already changed to a state that means the same as our
> > previous WORKING.
>
> In case of 'local add, incoming add', I believe what happens is that
> the incoming file is installed in BASE, and the locally added file is
> only in WORKING and ACTUAL.
>
> So <file> in working has not been changed, only the BASE tree has been
> changed and conflict markers have been installed.
>
> > *Problems*: Are we guarenteed that this always holds? Can the
> > rescheduling destroy the semantics of the change?
>
> We just need to offer an option to either keep the current WORKING
> file in WORKING or put the new BASE file in WORKING. Even if the local
> add was the destination of a copy, there are only those two options.
>
> We don't need to worry about destroying anything. Maybe keep an unversioned
> backup of whichever file was overwritten.
>
> > RENAME-MINE
> > ------------
> > Move the WORKING <file> to <renamed> and replace <file> with the new
> > BASE that comes in during update.
> >
> > MERGE
> > ------
> > Merge BASE <file1> onto WORKING <file2>. Delete <file1> from WORKING.
>
> See the options menu I suggested above.
>
> > 2. Locale del, incoming del
> > ============================
> > Some use cases:
> > - Already applied the patch -> want to do it just once -> THEIRS.
>
> ... or MINE, since both sides made the same change.

See comments above for the add/add case.

> > - Renamed to two different names -> want to undo Their renaming and
> > make it like Mine, as if we had a "Choose Mine" option that worked
> > on whole rename operations. -> RENAME.
>
> What about keeping their name?

See comments above for the add/add case.

> > THEIRS
> > -------
> > Delete the WORKING <file>. If the WORKING <file> has been moved to
> > <moved> then delete <moved> too.
>
> No, let's not follow moves/copies for now. We can add that later.
>
> > WORKING <file> is supposed to be
> > deleted in all cases so perhaps there's no need to specify it here?
> >
> > MINE
> > -----
> > WORKING-TARGET is already changed to a state that means the same as our
> > previous WORKING.
> >
> > RENAME
> > -------
> > Rename WORKING <file> to <renamed>. Merge BASE <file> onto WORKING
> > <renamed> if there are changes. Remove BASE <file>?
>
> Removing a file from BASE doesn't make any sense.
> Local changes aren't expressed in BASE.
>
> > 3. Locale del, incoming edit
> > ============================
> > Some use cases:
> > - Locally renamed -> want to apply the incoming mod to a different
> > item -> ELSEWHERE.
>
> This should be handled automatically without even prompting the user.
> wc-ng will provide this information.
> Note that it will also tell us whether the local operation was a move
> or a delete. In case of a true delete, the options below still apply.
>
> >
> > THEIRS
> > -------
> > Replace the deleted WORKING <file> with edited BASE <file>. If WORKING
> > <file> has been moved to WORKING <moved>, delete <moved>
>
> Again, don't bother checking for copies of the WORKING file for now.
>
> >
> > MINE
> > -----
> > WORKING-TARGET is already changed to a state that means the same as our
> > previous WORKING.
> >
> > ELSEWHERE1
> > -------------
> > If WORKING <file> has been moved to WORKING <moved>. Merge BASE <file>
> > onto WORKING <moved>. Does this preserve history?
>
> It does preserve history, since in wc-ng, we can trace from the old
> location of the WORKING file to where it has been moved to.
> And the moved file will have copyfrom info.
>
> >
> > ELSEWHERE2
> > -----------
> > TODO:
> >
> > 4. Locale edit, incoming del
> > ============================
> > Some use cases:
> > - The incoming change is (part of) a rename -> want to transfer my
> > local mod to the renamed item -> MOVE-MY-MODS.
>
> Or maybe keep my edit in the WOKRING file and move the new BASE file
> somewhere else?
>
> >
> > THEIRS
> > -------
> > Remove WORKING <file>. If WORKING <file> has been moved to WORKING
> > <moved>. Replace WORKING <moved> with BASE <moved>.
>
> You don't know <moved>, unless the user knows and can tell you.
>
> We can't tell the add-half of the rename for which you get the
> incoming delete-half. We can only do this once the server can tell
> us this information, i.e. we need wc-ng, and editorv2, and storing
> renames on the server sorted out. The latter hasn't even been started.
>
> >
> > MINE
> > -----
> > WORKING-TARGET is already changed to a state that means the same as our
> > previous WORKING.
>
> Yes, it's A+ as shown above.
>
> >
> > MOVE-MY-MODS1
> > -------------
> > If BASE <file> has been moved to BASE <moved>: Merge WORKING <file> onto
> > BASE <moved>. Delete WORKING <file>.
> >
> > MOVE-MY-MODS2
> > --------------
> > If BASE <file> has been moved to BASE <moved>: Merge BASE <moved> onto
> > WORKING <file>. Delete BASE <moved>. Move WORKING <file> to WORKING
> > <moved>.
>
> Again, for incoming renames, you don't know the name of the move target
> unless the user tells you.
>
> Stefan

- Julian
Received on 2009-12-02 13:58:07 CET

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.