Hello,
even though everyone has their heads wrapped around getting 1.5 out
the door, I'd like to report that Steve and I have gotten the tree
conflict branch to a milestone: Use cases 1 to 3 are now being handled
in a usable implementation.
Let me explain what this means in practice. Don't be afraid to read on
even if you've never heard of tree conflicts before.
I will try to describe what user-visible changes the tree-conflict
branch implements. Some of the following is copied and slightly adapted
from notes/tree-conflicts/use-cases.txt. See that file for reference
and some illustrative ASCII diagrams.
There are 3 use cases in which the tree-conflict branch's behaviour differs
from trunk's behaviour. I will illustrate the description of the first
use case with some commands and actual output so you can get a fairly good
idea of what the new behaviour looks like without having to checkout and
build the branch yourself. And if you want to see it for yourself no one
is stopping you from checking out the branch.
As usual, any feedback is welcome :)
Feedback on notes/tree-conflicts/detection.txt, which was recently committed
to trunk, would also be great. If you have the time to read it and have a
comment, we would like to hear from you.
-------------------
Use case 1:
Developer A modifies Foo.c and commits it to the repository.
$ cat Foo.c
foo
$ echo "Foo.c as modified by A" > Foo.c
$ svn ci -m "modified Foo.c"
Developer B has simultaneously moved Foo.c to Bar.c in his working
copy.
$ svn move Foo.c Bar.c
A Bar.c
D Foo.c
$ svn ci -m "renamed Foo.c to Bar.c"
Adding Bar.c
Deleting Foo.c
svn: Commit failed (details follow):
svn: File '/Foo.c' is out of date
B cannot commit because the working copy is out of date,
so B runs 'svn update'.
This is what now happens on current trunk (old behaviour):
The update will apply A's modifications to Foo.c in the
repository to Foo.c in B's working copy.
$ svn update
U Foo.c
Updated to revision 2.
Note again that Foo.c is marked for deletion in B's working copy.
So A's modification has been applied to a file marked as locally deleted.
The 'U Foo.c' may have escaped B especially if the update touches a lot
of files. B now does a commit.
$ svn ci -m "renamed Foo.c to Bar.c"
Adding Bar.c
Deleting Foo.c
Committed revision 3.
A's modification of Foo.c will effectively be reverted by B's new
revision. Foo.c will be deleted in the new revision, and Bar.c will be
added with the content of the original Foo.c before A's modifications.
Hence A will likely get angry with B.
Had B run "svn diff" before committing, he may have seen this:
$ svn diff Foo.c
Index: Foo.c
===================================================================
--- Foo.c (revision 2)
+++ Foo.c (working copy)
@@ -1 +0,0 @@
-Foo.c as modified by A
This is what happens on the tree conflict branch instead (new behaviour):
The update will apply A's modifications to Foo.c in the
repository to Foo.c in B's working copy. It will also put
the directory containing Foo.c into a state of conflict.
$ svn update
U Foo.c
C .
Updated to revision 2.
Note again that Foo.c is marked for deletion in B's working copy.
So A's modification has been applied to a file marked as locally deleted.
B now tries to do a commit, but the commit fails.
$ svn ci -m "renamed Foo.c to Bar.c"
svn: Commit failed (details follow):
svn: Aborting commit: '/tmp/wcB' remains in conflict
(Here, /tmp/wcB happens to be the working copy root, but a tree conflict
may be anchored at any directory in the working copy.)
B can now run "svn info" on the tree-conflicted directory to inquire
about the conflict, and decide what action to take to resolve it, possibly
discussing the proper fix with A.
$ svn info /tmp/wcB
Path: /tmp/wcB
URL: file:///tmp/repo
Repository Root: file:///tmp/repo
Repository UUID: eb86d84e-d4f0-407f-a0df-a893da9c5563
Revision: 2
Node Kind: directory
Schedule: normal
Last Changed Author: stsp
Last Changed Rev: 2
Last Changed Date: 2008-01-16 16:31:37 +0100 (Wed, 16 Jan 2008)
Tree conflicts:
The update edited the file 'Foo.c'.
You have deleted 'Foo.c' locally.
Maybe you renamed it?
Note the last few lines in the output. (Whether this is the right
place to put this information, and whether it has the right format
is still open for debate. See http://svn.haxx.se/dev/archive-2008-01/0098.shtml)
Once B has resolved the tree conflict, e.g. by moving the local
modifications made to the locally deleted Foo.c to Bar.c, B runs
"svn resolved" on the tree-conflicted directory.
$ svn diff Foo.c
Index: Foo.c
===================================================================
--- Foo.c (revision 2)
+++ Foo.c (working copy)
@@ -1 +0,0 @@
-Foo.c as modified by A
$ cat Bar.c
foo
$ echo "Bar.c as modified by A" > Bar.c
$ svn diff
Index: Foo.c
===================================================================
--- Foo.c (revision 2)
+++ Foo.c (working copy)
@@ -1 +0,0 @@
-Foo.c as modified by A
Index: Bar.c
===================================================================
--- Bar.c (revision 1)
+++ Bar.c (working copy)
@@ -1 +1 @@
-foo
+Bar.c as modified by A
Property changes on: Bar.c
___________________________________________________________________
Added: svn:mergeinfo
$ svn resolved /tmp/wcB
Resolved conflicted state of '/tmp/wcB'
B now does a commit. Barring no other conflicts (of any kind)
the commit will succeed.
$ svn ci -m "renamed Foo.c to Bar.c"
Adding Bar.c
Deleting Foo.c
Transmitting file data .
Committed revision 3.
-------------------
Use case 2:
Developer B modifies Foo.c in his working copy.
Developer A has simultaneously moved Foo.c to Bar.c and commits
the move to the repository.
B cannot commit because his working copy is out of date, so B runs
'svn update'.
This is what now happens on current trunk (old behaviour):
The update will add Bar.c (with the same content as the original Foo.c)
to B's working copy, and delete Foo.c from B's working copy.
Since B made local modifications to Foo.c, it will not be deleted from
disk but left behind unversioned.
B's source tree in the working copy likely builds fine because Foo.c
is still present on disk.
Assuming B does not notice that Foo.c fell out of version control,
an incomplete change set may get committed, possibly breaking the tree.
This is what happens on the tree conflict branch instead (new behaviour):
The update will add Bar.c (with the same content as the original Foo.c)
to B's working copy, and delete Foo.c from B's working copy.
The directory containing Foo.c will be put in a state of conflict.
Since B made local modifications to Foo.c, it will not be deleted from
disk but left behind unversioned.
B's source tree in the working copy likely builds fine because Foo.c
is still present on disk.
B now tries to do a commit, but the commit fails because of the
tree-conflicted directory.
B can now run "svn info" on the tree-conflicted directory to inquire
about the conflict, and decide what action to take to resolve it.
Once B has resolved the tree conflict, B runs "svn resolved" on the
tree-conflicted directory.
B now does a commit. Barring no other conflicts (of any kind)
the commit will succeed.
-------------------
Use case 3:
Developer A moves Foo.c to Bar.c and commits the move to the repository.
Developer B has moved Foo.c to Bix.c in his working copy.
B cannot commit because his working copy is out of date, so B runs
'svn update'.
This is what now happens on current trunk (old behaviour):
The update will add Bar.c to B's working copy and
delete Foo.c from B's working copy (the latter is a no-op).
B now does a commit.
After B's commit, the content of the original Foo.c will exist
twice in the source tree under two different paths, namely Bar.c
and Bix.c, respectively.
This is what happens on the tree conflict branch instead (new behaviour):
The update will add Bar.c to B's working copy and
delete Foo.c from B's working copy (the latter is a no-op).
The directory containing Foo.c will be put in a state of conflict.
B now tries to do a commit, but the commit fails because of the
tree-conflicted directory.
B can now run "svn info" on the tree-conflicted directory to inquire
about the conflict, and decide what action to take to resolve it.
Once B has resolved the tree conflict, B runs "svn resolved" on the
tree-conflicted directory.
B now does a commit. Barring no other conflicts (of any kind)
the commit will succeed.
--
Stefan Sperling <stsp_at_elego.de> Software Developer
elego Software Solutions GmbH HRB 77719
Gustav-Meyer-Allee 25, Gebaeude 12 Tel: +49 30 23 45 86 96
13355 Berlin Fax: +49 30 23 45 86 95
http://www.elego.de Geschaeftsfuehrer: Olaf Wagner
- application/pgp-signature attachment: stored
Received on 2008-01-16 18:01:20 CET