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

Re: [RFC] v2 Tree conflict resolver spec.

From: Neels J Hofmeyr <neels_at_elego.de>
Date: Tue, 16 Feb 2010 12:51:40 +0100

Julian Foad wrote:
> On Wed, 2010-02-10, Neels J Hofmeyr wrote:
>> Hi TC folks,
>>
>> I tried to put the tree-conflicts design information so far into tables.
>
> Thanks, Neels. This is a really useful way to present the info.

thanks :)

>> Find the result attached: a tc-cheatsheet up for discussion. If it gets
>> initial approval I'll check it into notes/tree-conflicts/ so we can edit.
>
> [...]
>
>> plain text document attachment (tc-cheatsheet.txt)
>> TREE CONFLICT CHEAT SHEET (DESIGN PHASE)
>>
>>
>> After tree | 'theirs' | 'mine' is | 'svn status' shows
>> conflict during | is found in | found in | TC and is otherwise
>> -----------------+-------------------+----------------+---------------
>> | | |
>> update/switch | checked-out state | check-in state | adapted to be a
>> | | (unchanged) | mod of the new
>> | | | checked-out state
>> | | |
>> merge | conflict info | check-in state | unchanged
>> | | (unchanged) |
>> | | |
>>
>>
>>
>>
>> Upon recording | ... changed during |
>> a tree conflict, is | update/switch? | merge? |
>> ----------------------------+----------------+----------------+
>> checked-out state | Yes | No |
>> check-in state | No | No |
>> 'svn status' other than TC | Yes | No |
>>
>>
>>
>>
>> When resolving a | ...which was caused by a |
>> tree-conflict with | switch/update | merge |
>> | , the check-in state is |
>> ----------------------+-----------------------------------+
>> | | |
>> --accept=theirs | cleared | reset to theirs |
>> | | |
>> --accept=mine | unchanged | unchanged |
>> | | |
>> 'svn revert' | cleared | cleared |
>> | | |
>
> All the above: +1.

Nice. This is the next step. I've started verifying this behaviour, and
especially with add vs. add, we are quite off. I'm hitting situations (also
in 'svn diff' and 'svn cat') where there is a revert-base but no text-base
(which the current code fails at), or where the previous text-base's
checksum is confused with a locally replaced node's checksum; they would
take quite some spaghetti to fix. I've come to the conclusion that it makes
much more sense to use wc-ng than wc-1 concerning the text-base. I've
decided to rather help push the pristine store a little, so that we don't
need to fix behaviour concerning text-base/revert-base file confusion, and
to then come back to TC add-vs-add, diff_wc_url and from that
incoming-delete-should-not-delete-modified-tree.
The tail is getting longer :)

From Julian's remarks below (thanks, Julian!), I note many shortcomings in
what I wrote below. Maybe we can find a solution for the circular move (with
and without edits) that also includes the simpler cases for free?

I am getting a feeling that it would make sense to only offer resolving
*this* path (at least to begin with), so that a circular move needs explicit
resolution at each point of the circle, and that each resolution is
independent of resolving the other paths involved. That would mean to also
flag tree-conflicts at the *other* paths (e.g. moved-away-to or
moved-here-from paths), so that the user remembers to also decide for the
other ends whether anything should change...

The game is on! :)

~Neels

* neels heads over to the pristine store lab

>
>
>> <future depends-on="editor-v2" status="needs-review">
>>
>> Assuming that we have full info on copy/move (i.e. an add here is really
>> just an add and *not* possibly part of a copy/move), then:
>>
>> When resolving a |
>> tree-conflict of |
>> local vs. | incoming | offer these --accept= resolution options
>> ===========+===========+=====================================================
>> | |
>> (all combinations of) |
>> add | add | theirs, mine, move-theirs, move-mine
>> copy-here | copy-here |
>> move-here | move-here |
>
> We also want to offer some kind of "auto-merge" option which keeps one
> version (just like "theirs" and like "mine") if both are identical, and
> offers some kind of merging if they differ. Or which re-prompts if they
> differ. Or the initial prompt should differ depending on whether the two
> added things differ. It gets complex with directories, and with
> differences in copy-from but identical content, etc.
>
>> | |
>> -----------+-----------+-----------------------------------------------------
>> | |
>> delete | delete | (is not a tree-conflict)
>
> I agree that most users will want this silently allowed. That's a
> sensible behaviour for "svn".
>
> Theoretically, however, that's only true in the same sense that
> add-on-add is not a tree conflict if the same node is added twice: it's
> an assumption that the user doesn't ever want to know about this kind of
> conflict. Some users in some merging tasks will want a strict mode,
> where they are not expecting any double-deletes and would like it
> flagged if it happens.
>
> Somehow I want to introduce a "conflict rules" framework, not
> necessarily accessible through the "svn" UI, but within the
> implementation and APIs. The rules will be a read-only context passed in
> from the client that is like a table saying "delete-delete is to be a
> silent delete, add-add is to be flagged as a conflict, edit-rename is to
> be a silent edit of the renamed file, ...".
>
> Then it will be easy for people to write a client that behaves more or
> less strictly without having to first rev all our APIs.
>
> And a second issue with "delete + delete": in a merge, we have to
> consider whether the two things being deleted were identical. I haven't
> yet tried to expand the rules to take account of that.
>
> I *think* the same considerations also apply to all the other cases that
> involve a delete during a merge.
>
>> | |
>> -----------+-----------+-----------------------------------------------------
>> | |
>> (line-wise) |
>> delete | move-away | (is not a tree-conflict)
>> move-away | delete |
>> | |
>> -----------+-----------+-----------------------------------------------------
>> | |
>> (line-wise) |
>> delete | edit | theirs, mine
>> edit | delete |
>> | |
>> -----------+-----------+-----------------------------------------------------
>> | |
>> move-away | edit | mine, both, merge-here, merge-there,
>> | | merge-there-keep-here, merge-there-merge-here
>> | | [1] [2]
>> | | grain of salt ---> .
>
> Heh!
>
> But "merge-there" is surely the almost universal wish, just like "delete
> + delete -> delete" and "add + add -> add" when the two adds are
> identical are almost universal wishes.
>
> "merge-here" just means the same as "theirs", doesn't it? We need to
> keep options called "mine" and "theirs" in every menu, because they
> always make sense, even if we annotate them with extra description such
> as "theirs (undo the move and merge the incoming edit here)".
>
> What is "merge-there-keep-here" for? I can't think of a realistic use
> case.
>
> What is "merge-there-merge-here" for? In the case of a copy rather than
> a move, then yes I can see users wanting the incoming change applied to
> both copies, but for a move?
>
> Ugh. Moves and copies get very complex. Partly because any move can have
> an edit as well. Partly because the destination location might also be a
> location from where something was moved away at the same time (perhaps
> also being in conflict, in which case we'd require that it be resolved
> first ... unless it's a cycle of moves like A>B, B>A or A>B, B>C, C>A in
> which case they might have to be resolved all at the same time).
> Seriously, the design has to cope with not falling over in these cases,
> though we certainly don't have to give special friendly options, just so
> long as there is some way for the user to resolve it.
>
>> -----------+-----------+-----------------------------------------------------
>> | |
>> edit | move-away | theirs, both, merge-here, merge-there,
>> | | merge-there-keep-here, merge-there-merge-here
>> | | [1] [2]
>> | | grain of salt ---> .
>> -----------+-----------+-----------------------------------------------------
>> | |
>> move-away | move-away | theirs, mine, both, merge-at-theirs, merge-at-mine,
>> | | merge-at-theirs-keep-mine, merge-at-mine-keep-theirs,
>> | | merge-at-both
>> | | (not a tree-conflict when move targets match)
>> | | [1] [2]
>> | | grain of salt ---> .
>
> Ugh. This case gets even more complex.
>> -----------+-----------+-----------------------------------------------------
>>
>
> We'll need to define copies as well :-/
>
>>
>> Where the --accept= options mean:
>>
>> mine Enforce my change, make sure theirs is lost/undone.
>> theirs Agree to theirs, make sure mine is lost.
>> move-theirs Keep both additions, but move theirs to another path.
>> move-mine Keep both additions, but move mine to another path.
>> both Keep both new move-targets (one becomes a simple "A +").
>> merge-there Apply the edit to the moved-away path.
>> merge-here Discard the move-away, but still merge text/prop mods.
>> merge-there-keep-here Apply text/prop mods to the moved-away path, but
>> keep an unmerged copy at this path.
>> merge-there-merge-here Apply text/prop mods to the moved-away path, and
>> keep another, also merged, copy at this path.
>> merge-at-theirs Apply the edits on my moved-away path to their moved-
>> away path, discard my move.
>> merge-at-mine Apply the edits on their moved-away path to my moved-
>> away path, discard their move.
>> merge-at-theirs-keep-mine Apply the edits on my moved-away path to their moved-
>> away path, but keep my move-away with only *its* edits.
>> merge-at-mine-keep-theirs Apply the edits on their moved-away path to my moved-
>> away path, but keep their move-away with only *its*
>> edits.
>> merge-at-both Apply all edits to all moved-away paths and keep them.
>>
>> [1] I am not sure whether resolution should only care about *this* path.
>> Some of the resolution options suggest that we would undo the add-part
>> of a move-away, at the *other* path, or apply edits to the *other* path.
>> While it would be nicer if we could get away with only resolving *this*
>> path, users might get annoyed with having to do two steps to get what
>> they wanted (i.e. manually modify the other path to the desired result)
>> when the resolver had all the information there and could have just done
>> the job automatically.
>>
>> [2] The merge-* options indicate a mixture of text/prop mods with tree
>> conflicts. They say whether to keep the respective sides' text/prop mods
>> when resolving the tree-conflict. These options would entail that we
>> have to run an apply-textdelta-ish code that can introduce new text/prop
>> conflicts.
>> Should we really go there? What are the alternatives? We won't get away
>> without defining what happens to text/prop mods at two different paths
>> that are related via moves.
>> ### Analogy to copies?
>>
>> </future>
>>
>
> - Julian
>
>

Received on 2010-02-16 12:52:25 CET

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