blob: dcf2ccbc8598e9bd138c5bd039b596c1f0b291de [file] [log] [blame]
-*- text -*-
This file is a scratch pad for working out current and expected
behaviors for various tree-conflict situations. It may be considered
unfinished at best -- scatterbrained is more like it.
NOTE: As Subversion does not actually have real 'move' functionality,
please try to express move-ish use-cases in terms of deletes and
adds-with-history (copies).
===================
BACKGROUND THOUGHTS
===================
This whole thing is, I think, basically about ensuring that the
history of a file isn't allowed to fork and then suffer the
unceremonious death of one of the two resulting lines of history when
the streams are rejoined.
When doing an update, we don't have to worry that the working copy
base file has deviated from the line of history that's being deleted
-- other processes prevent this from happening (you can't commit
to a deleted file; you can't delete a file that's been modified since
you last updated). But you do have to worry about local mods, which
are a "different path" in the file's line of history than the path
that led to its deletion.
When doing a merge, though, stuff gets really complicated. Now you
have an arbitrary line of history as the source which you are trying to
"lay down" overtop the line of history of the stuff in your
repository, and the goal remains the same: don't assume that
deviations in those lines should be resolved by disregarding one side
of the fork or the other -- that's ungood. In the best case you are
trying to append segments of one fork in the history road to the
other, and hopefully you don't leave gaps or cause deviations. In the
worst case, though, you're dealing with a "line of history" that's
made up on-the-fly (due to your left- and right-side merge sources
being unrelated, or only related as second cousins twice removed, or
something). This is where the "merge = diff + patch" paradigm really
starts to show its weaknesses (and maybe, just maybe, should have been
a use-case that Subversion disallowed ... if only it weren't so darned
useful for vendor branches...).
Anyway, there appear to me to be some pretty clear goals:
* Conflicting operations should be marked as such and require user
interaction to resolve
* In such a conflicting situation, users would like to be able to
easily do the following:
- determine what local mods they've made
- apply those mods elsewhere if necessary
- determine what mods conflict with the ones with they
- overrule the conflict and make their changes anyway
* Tree conflicts appear to be something special, and should be
annotated as such.
So a tree conflict is really just a conflict on the content of a
directory, much like a regular conflict is on the content of a file,
and a prop conflict is on the properties of a file or directory. To
annotate a tree conflict, we recycle the 'conflict-new' conflict file
slot pointing to a dropped file named dir_contents.trej. It's
contents can note the details of the tree conflict. [### TODO: Do we
need to be able to mark files as tree-conflicted, too?]
===================
SCENARIO PLAYGROUND
===================
'svn update' pulls file deletion atop file with local text mods
NOW: File is silently unversioned.
NEW: File is marked as added-with-history (as of the revision
previously in the working copy), and placed into a state of
conflict. There are no conflict markers, but the .trej file
notes that our file was deleted in the repository. User can
see mods with 'svn diff'; revert still works; resolved+commit
undoes the deletion and commits the users's mods.
'svn update' pulls text mods onto schedule-delete file
NOW: Text mods are silently merged into file's text-base and file
remains scheduled for deletion.
NEW: File remains scheduled for deletion, text-base is up-to-date,
but file is marked as conflict, and .trej file notes that
the file was modified in the repository.
QUESTION: Should .trej file contain the diff of those mods
from the repository?
'svn update' pulls dir deletion atop dir containing deep text mods
NOW: Directory is removed save for modified files (left
unversioned).
NEW: Modified files are marked as added-with-history (as of their
working copy revisions), placed into a state of conflict, with
.trej files noting the deletion of the parent directory.
Intermediate directories are marked as added (no history) and
in conflict, with their .trej files noting the deletion of the
directory.
'svn update' pulls file replacement atop modified file
NOW: Behaves as a two-step action: delete over modified file (see
above), then file add over existing file (which is obstructed
unless --force is provided.
NEW: If the 'delete' step goes as recommended above, we'll wind up
in a state of conflict already with a schedule-added file.
Once the 'add' step hits, the operation will be obstructed
even if --force is provided.
QUESTION: Is this desirable? What's the final state of the
file after the failed update? How do the recovery options
play out from here? For example, we wouldn't want the file
scheduled for add-with-history because that commit can't
succeed (another file already exists in the repository at
that location).
'svn update' pulls dir replacement atop deep-modified directory
'svn update' pulls file-to-dir replacement atop modified file
NOW: Behaves as a two-step action: delete over modified file (see
above), then directory add over existing file (which is
disallowed, even if --force is supplied).
NEW:
'svn update' pulls dir-to-file replacement atop deep-modified directory
NOW: Behaves as a two-step action: delete over deep-modified
directory (see above), then file add over existing directory
left over from delete step (which fails).
NEW:
'svn merge' pulls file deletion
NOW: If there's nothing at the target location to delete, the
target is "skipped" (?); otherwise the target is removed from
version control and, if not locally modified, deleted.
NEW: All file deletions that would affect a local file and that come
via merge get sanity-checked, with the client pulling the
left-side source version of the file down and comparing its
contents with the to-be-deleted working file. If they are
equivalent and there are no local mods to the file, it is
removed from version control. Otherwise, we have two sets of
data we'd like to keep easy track of: diffs between
deleted-source and wc base file, and diffs between wc base and
wc working files.
NOTE: Need more thinkin' 'round these parts...
'svn merge' pulls file modification atop schedule-delete file
NOW: "Skipped missing target" message.
NEW: File remains scheduled for deletion, but working file is
restored (if missing), marked as conflicted, and contents
carry conflict info.
'svn merge' pulls file modification atop missing file
NOW: "Skipped missing target" message.
NEW:
'svn merge' pulls file modification atop added file
NOW: Conflict!
NEW: Conflict!