| -*- text -*- |
| |
| TREE CONFLICTS USE CASES AND DESIRED BEHAVIOURS |
| |
| |
| Issue reference: https://issues.apache.org/jira/browse/SVN-2282 |
| https://issues.apache.org/jira/browse/SVN-3630 |
| |
| These use cases are based on a scenario paper "SVN move/rename |
| problems & suggested improvements" submitted by a corporate Subversion |
| user, which may be found attached to issue #2282. |
| |
| These notes were originally written during development of Subversion 1.6. |
| The original version focussed on detection of tree conflicts. The notes |
| have since been updated with behaviour changes up to Subversion 1.8. |
| Any 'desired behaviour' mentioned here is yet to be implemented. |
| |
| -------------------------------------------------------------------------- |
| |
| ========== |
| USE CASE 1 |
| ========== |
| |
| Description |
| |
| During an update, a file modification is merged onto a file move. |
| |
| Behavior of Subversion <= 1.5 |
| |
| Developer A modifies Foo.c and commits it to the repository. |
| |
| Developer B has simultaneously moved Foo.c to Bar.c in his working |
| copy. |
| |
| B cannot commit because the working copy is out of date, so B runs 'svn |
| update'. The update will apply A's modifications to Foo.c in the |
| repository to Foo.c in B's working copy. |
| |
| Problems With Behavior of Subversion <= 1.5 |
| |
| First problem: |
| |
| 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. |
| |
| Second problem: |
| |
| B is not explicitly warned about reverting A's modification of Foo.c. |
| The only visible warning is that Foo.c is left behind unversioned in |
| B's working copy because it has "local" modifications (which were in |
| fact made by A). This will likely escape B's attention. |
| |
| Diagram of behavior of Subversion <= 1.5 |
| |
| |
| (edit) |
| wcA -- Foo.c' -------> |
| / | |
| / |commit |
| repos / v |
| -- Foo.c -------------- Foo.c' --------------- Bar.c ---> |
| \ | ^ |
| \ |update |commit |
| \ v | |
| wcB -- +Bar.c ---------- +Bar.c ---- Bar.c ---> |
| (move) -Foo.c -Foo.c' ?Foo.c' (unversioned) |
| |
| Behaviour of Subversion >= 1.6 |
| |
| Foo.c will be deleted from B's working copy. |
| |
| A tree conflict is signalled to inform B of the new changes to Bar.c, |
| so that B can review the modified Bar.c before committing it. |
| |
| Behavior of Subversion >= 1.8 |
| |
| As above, a tree conflict is flagged on Foo.c. |
| |
| When user B resolves the tree conflict on Foo.c, A's modifications |
| to Foo.c will be merged into Bar.c. |
| |
| Text/Prop conflicts are signalled necessary. |
| |
| Diagram of Behaviour of Subversion >= 1.8 |
| |
| |
| (edit) |
| wcA -- Foo.c' -------> |
| / | |
| / |commit |
| repos / v |
| -- Foo.c --------------- Foo.c' ------------------------ Bar.c' ---> |
| \ | ^ ^ |
| \ |update |commit |commit |
| \ v |(fails) | |
| wcB -- +Bar.c ------------ +Bar.c' --------------> |
| (move) -Foo.c -Foo.c ^ |
| | |
| resolved |
| |
| |
| ========== |
| USE CASE 2 |
| ========== |
| |
| Description |
| |
| During an update, a file move is merged onto a file modification. |
| |
| This is essentially the same as Use Case 1, with the difference that |
| this time, B does the edit and A does the move. |
| |
| Behavior of Subversion <= 1.5 |
| |
| 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'. The next 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. |
| |
| Problems with behavior of Subversion <= 1.5 |
| |
| Developer B may not notice that Foo.c fell out of version control. |
| B's source tree in the working copy likely builds fine because Foo.c |
| is still present on disk. So B may commit an incomplete change set, |
| possibly breaking the tree. Everybody will get angry with B if this |
| happens. |
| |
| Diagram of Behaviour of Subversion <= 1.5 |
| |
| |
| (move) |
| wcA -- +Bar.c -------> |
| / -Foo.c | |
| / |commit |
| repos / v |
| -- Foo.c --------------- Bar.c -----------------------> |
| \ | ^ |
| \ |update |commit |
| \ v |(no-op) |
| wcB -- Foo.c' ------------ Bar.c -------> |
| (edit) ?Foo.c' (unversioned) |
| |
| Behavior of Subversion >= 1.6 |
| |
| When B updates, Bar.c is added to B's working copy, and a tree conflict |
| is flagged on Foo.c. B is expected to figure out that A renamed Foo.c |
| to Bar.c, and must resolve the conflict in some way before committing. |
| |
| Desired Behavior |
| |
| In B's working copy, the update should add Bar.c and merge the local |
| modifications to Foo.c into Bar.c. Signal a text conflict if necessary. |
| |
| Foo.c should be deleted from B's working copy. |
| |
| A tree conflict should be signaled to inform B that Foo.c has been |
| renamed to Bar.c |
| |
| Diagram of Desired Behaviour |
| |
| |
| (move) |
| wcA -- +Bar.c -------> |
| / -Foo.c | |
| / |commit |
| repos / v |
| -- Foo.c --------------- Bar.c -------------------------- Bar.c'---> |
| \ | ^ ^ |
| \ |update |commit |commit |
| \ v |(fails) | |
| wcB -- Foo.c' ------------+Bar.c' ------------------------> |
| (edit) -Foo.c' ^ |
| | |
| resolved |
| |
| |
| ========== |
| USE CASE 3 |
| ========== |
| |
| Description |
| |
| During an update, a file move is merged onto a conflicting file move. |
| |
| Behavior of Subversion <= 1.5 |
| |
| 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'. 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). |
| |
| Problems with behavior of Subversion <= 1.5 |
| |
| After B's next 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 may not have been intended. |
| |
| Diagram of behavior of Subversion <= 1.5 |
| |
| |
| (move) |
| wcA -- +Bar.c ------> |
| / -Foo.c | |
| / |commit |
| archive / v |
| -- Foo.c --------------- Bar.c ------------------ Bar.c ---> |
| \ | ^ Bix.c |
| \ |update |commit |
| \ v | |
| wcB -- +Bix.c ---------- +Bix.c -------> |
| (move) -Foo.c Bar.c |
| |
| |
| Behavior of Subversion >= 1.6 |
| |
| A tree conflict is signaled to inform B of the conflicting rename |
| operation. B can now decide on deleting either file or committing both. |
| |
| Diagram of behavior of Subversion >= 1.6 |
| |
| |
| (move) |
| wcA -- +Bar.c ------> |
| / -Foo.c | |
| / |commit |
| archive / v |
| -- Foo.c --------------- Bar.c -------------------------- Bar.c --> |
| \ | ^ ^ (or Bix.c, |
| \ |update |commit |commit or both) |
| \ v |(fails) | |
| wcB -- +Bix.c ---------- +Bix.c --------------> |
| (move) -Foo.c Bar.c ^ |
| | |
| resolved |
| |
| Problems with Behaviour of Subversion >= 1.6 |
| |
| The incoming move is labeled as 'incoming delete' in the tree |
| conflict description, rather than 'incoming move'. No assistance |
| is provided while resolving the tree conflict. Inexperienced users |
| are often unsure why the conflict occurred and don't know how to |
| proceed. |
| |
| ========== |
| USE CASE 4 |
| ========== |
| |
| Description |
| |
| A file modification is merged onto the source of a file move. |
| |
| Behavior of Subversion <= 1.5 |
| |
| Developer A modifies Foo.c and commits it to the repository. |
| |
| Developer B moves Foo.c to Bar.c and commits it to the repository. |
| |
| Developer B merges A's new revision into his working copy. The merge |
| will apply A's modification to Foo.c to the Foo.c in B's working |
| copy. |
| |
| Problems With behavior of Subversion <= 1.5 |
| |
| First problem: |
| |
| A's modification of Foo.c will not be merged to B's line of |
| development because the merge skips the absent file. |
| |
| Second problem: |
| |
| B is not explicitly warned about reverting A's modification of Foo.c, |
| except for a "skipped" warning in the output of the merge command, |
| which might not be noticed. |
| |
| Diagram of behavior of Subversion <= 1.5 |
| |
| |
| (edit) |
| urlA -- Foo.c' ------------------> |
| / (r50) | |
| / | |
| -- Foo.c - |merge -c50 |
| \ |(Foo.c skipped) |
| \ | |
| urlB -- +Bar.c ------------|-----------------> |
| (move) -Foo.c \ | ^ |
| \ | |commit |
| \ v |(no-op) |
| wcB -- Bar.c -- Bar.c ------ --> |
| |
| |
| Behavior of Subversion >= 1.6 |
| |
| A tree conflict is signalled to inform B of the new changes to Bar.c, |
| so that B can review the modified Bar.c before committing it. |
| |
| Diagram of Behaviour of Subversion >= 1.6 |
| |
| |
| (edit) |
| urlA -- Foo.c' ------------------> |
| / (r50) | |
| / | |
| -- Foo.c - |merge -c50 |
| \ |(tree conflict) |
| \ | |
| urlB -- +Bar.c -------------|-------------------- Bar.c' --> |
| (move) -Foo.c \ | ^ ^ |
| \ | |commit |commit |
| \ v |(fails) | |
| wcB -- Bar.c -- Bar.c' ---------------> |
| ^ |
| | |
| resolved |
| |
| Problems with Behaviour of Subversion >= 1.6 |
| |
| No assistance is provided while resolving the tree conflict. |
| Inexperienced users are often unsure why the conflict occurred |
| and don't know how to proceed. |
| |
| Desired Behaviour |
| |
| When user B merges, A's modifications to Foo.c should be merged into |
| Bar.c. Signal a text conflict if necessary. |
| |
| |
| ========== |
| USE CASE 5 |
| ========== |
| |
| Description |
| |
| A file move is merged onto a modification of the move-source. |
| |
| This is essentially the same as Use Case 4, with the difference that |
| this time, B does the edit and A does the move. |
| |
| Behavior of Subversion <= 1.5 |
| |
| Developer A moves Foo.c to Bar.c and commits it to the repository. |
| |
| Developer B modifies Foo.c and commits it to the repository. |
| |
| Developer B merges A's new revision into his working copy. The merge |
| will add Bar.c (with the same content as the original Foo.c) and |
| will delete B's Foo.c. |
| |
| Problems with behavior of Subversion <= 1.5 |
| |
| B's has modified Foo.c in the past. This modification will be lost |
| unless B reviews the history of Foo.c and Bar.c at both URLs and |
| corrects the problem (e.g., via 'svn copy'). |
| |
| Diagram of behavior of Subversion <= 1.5 |
| |
| |
| (move) |
| urlA -- +Bar.c -------------------> |
| / -Foo.c | |
| / (r50) | |
| -- Foo.c - |merge -c50 |
| \ | |
| \ | |
| urlB -- Foo.c' -------------|------------ Bar.c ---> |
| (edit) \ | ^ |
| \ | |commit |
| \ v | |
| wcB -- Foo.c' -- +Bar.c ------> |
| -Foo.c' |
| |
| |
| Behavior Subversion >= 1.6 |
| |
| A tree conflict is signaled on Foo.c to inform B that Foo.c has been |
| renamed to Bar.c |
| |
| Problems with Behaviour of Subversion >= 1.6 |
| |
| The incoming move is labeled as 'incoming delete' in the tree |
| conflict description, rather than 'incoming move'. No assistance |
| is provided while resolving the tree conflict. Inexperienced users |
| are often unsure why the conflict occurred and don't know how to |
| proceed. |
| |
| Behavior of Subversion <= 1.8 |
| |
| Same as 1.6, but also for directories instead of just files. |
| |
| Desired behavior |
| |
| In B's working copy, the update should add Bar.c and merge the local |
| modifications to Foo.c into Bar.c. Signal a text conflict if necessary. |
| |
| Foo.c should be deleted from B's working copy. |
| |
| Diagram of Desired Behaviour |
| |
| |
| (move) |
| urlA -- +Bar.c -------------------> |
| / -Foo.c | |
| / (r50) | |
| -- Foo.c - |merge -c50 |
| \ |(tree conflict) |
| \ | |
| urlB -- Foo.c' -------------|-------------------- Bar.c'--> |
| (edit) \ | ^ ^ |
| \ | |commit |commit |
| \ v |(fails) | |
| wcB -- Foo.c' -- Bar.c' ---------------> |
| -Foo.c' ^ |
| | |
| resolved |
| |
| ========== |
| USE CASE 6 |
| ========== |
| |
| Description |
| |
| A file move is merged onto a conflicting file move. |
| |
| Behavior of Subversion <= 1.5 |
| |
| Developer A moves Foo.c to Bar.c and commits it to the repository. |
| |
| Developer B moves Foo.c to Bix.c and commits it to the repository. |
| |
| Developer B merges A's new revision into his working copy. The merge |
| will add Bar.c with history in B's working copy. |
| |
| Problems with behavior of Subversion <= 1.5 |
| |
| After B's next commit, the content of the original Foo.c will exist |
| twice in the source tree under two different paths (Bar.c and |
| Bix.c). This may not have been intended. |
| |
| Diagram of Behavior of Subversion <= 1.5 |
| |
| |
| (move) |
| urlA -- +Bar.c ------------------> |
| / -Foo.c | |
| / (r50) | |
| -- Foo.c - |merge -c50 |
| \ | |
| \ | |
| urlB -- +Bix.c ------------|---------------- Bix.c ---> |
| (move) -Foo.c \ | ^ Bar.c |
| \ | |commit |
| \ v | |
| wcB -- Bix.c -- Bix.c ----------> |
| +Bar.c |
| |
| |
| Behavior of Subversion <= 1.6 |
| |
| A tree conflict is flagged on Foo.c in B's working copy. |
| |
| Problems with Behaviour of Subversion >= 1.6 |
| |
| The incoming move is labeled as 'incoming delete' in the tree |
| conflict description, rather than 'incoming move'. No assistance |
| is provided while resolving the tree conflict. Inexperienced users |
| are often unsure why the conflict occurred and don't know how to |
| proceed. |
| |
| Desired behavior |
| |
| A tree conflict should be signaled to inform B of the conflicting |
| rename operation. B can delete either file or commit both. |
| |
| Diagram of Desired Behaviour |
| |
| |
| (move) |
| urlA -- +Bar.c -----------------> |
| / -Foo.c | |
| / (r50) | |
| -- Foo.c - |merge -c50 |
| \ |(tree conflict) |
| \ | |
| urlB -- +Bix.c ------------|------------------------- Bar.c --> |
| (move) -Foo.c \ | ^ ^ (or Bix.c, |
| \ | |commit |commit or both) |
| \ v |(fails) | |
| wcB -- Bix.c -- Bix.c --------------> |
| +Bar.c ^ |
| | |
| resolved |
| |