Subversion has always tried to skirt the issue of tree conflicts. By "tree conflict", we're talking about
issues where two users try to do contradictory things to the tree:
* both users try to add the same path, or
* one user tries to modify a path, and another tries to delete it
(The case of two users trying to delete the same path isn't a problem, since that's a mergeable tree
We're currently handling the first sort of tree conflict in a reasonable manner: 'svn up' bails out when
an existing path blocks its attempt to add a new path, and 'svn commit' will fails if it attempts to add a
path that already exists in the repository. There's a since symmetry there.
But in the second type of tree conflict, we're being quite unfriendly:
A. repos receives deletion; client updates onto a locally edited file.
==> locally edited file silently becomes unversioned (!)
B. repos recieves file change; client updates onto a schedule-delete file.
==> changes are silently merged into text-base (!)
C. repos receives deletion; client commits locally edited file.
==> out-of-date commit error.
D. repos receives file change; client commits deletion of file.
==> out-of-date commit error.
Cases (C) and (D) are reasonable, but a whole bunch of users have complained about behaviors (A) and
(B), especially (A).
Case B seems reckless: the user is now about to commit the deletion of a file, the latest of which he's
never even seen. We tell people that utilities like svnput.c are dangerous for *exactly* this reason, yet
here we are allowing to happen so easily.
Case A has frustrated users over and over. The user has 57 edited files, and then runs 'svn update'. Is
he really going to notice that *one* file has suddenly gone missing from the changeset? If 'svn status'
shows dozens of "M" files and dozens of "?" files (as is often the case), a user just doesn't notice that a
former 'M' has been converted to '?'. Their latest edits aren't lost forever, but they're definitely lost in
the shuffle; they never get committed, when the user thinks they have been.
The real reason we've not yet done anything about case (A) is that it gets very complex once you start
talking about directories. For example, what if the update tries to delete some parent directory of your
edited file? Do we set the whole directory into a state of conflict? How far can the update run before
bailing out? Our 1.0 solution was to bail completely on the problem and just "make everything
unversioned." But it's time to do better. As ghudson says, "we shouldn't let the perfect be the enemy
of the good."
We can certainly solve a chunk of the problem by marking individual files as (C)onflicted. It will take a
bit of design work in libsvn_wc. What we need to do is expand our concepts of conflict-marking. Right
now it always means there's a textual conflict, with three fulltexts left behind, etc. We need a way to
mark a file Conflicted when it's schedule-delete but new changes have come from the repository, and a
way to mark a file Conflicted when it's locally edited, but deleted by the last update. This will solve 80%
of users' pain.