Differences between revisions 7 and 8
Revision 7 as of 2012-01-18 12:46:19
Size: 6904
Editor: JulianFoad
Comment: Complex use case
Revision 8 as of 2013-09-03 09:13:11
Size: 8099
Editor: JulianFoad
Comment:
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
See "Keeping a Reintegrated Branch Alive" in the Svn Book here: http://svnbook.red-bean.com/en/1.6/svn-book.html#svn.branchmerge.advanced.reintegratetwice. ''The section on keeping a reintegrated branch alive became obsolete with the release of Subversion 1.8.''

----
= Keeping a Reintegrated Branch Alive =
A discussion on ways to improve the user experience when trying to keep using a branch after reintegrating it. This was a problem from Subversion 1.5 through Subversion 1.7. See "Keeping a Reintegrated Branch Alive" in the Subversion 1.6 Book here: http://svnbook.red-bean.com/en/1.6/svn-book.html#svn.branchmerge.advanced.reintegratetwice.
Line 5: Line 9:
Line 16: Line 19:
The sync merge r60 should take r50 but not r40.

The sync merge r60 should "take" the change r50 from A, but not r40. Subversion client versions 1.5 through 1.7 don't merge correctly at r60 without extra help such as that provided by the r45 commit.
Line 52: Line 57:
== Complex Use Case == Subversion 1.8 implements a solution superior to any of the above. The enhancement is announced [[http://subversion.apache.org/docs/release-notes/1.8.html#auto-reintegrate|in the 1.8 release notes]] and some design notes are in the [[SymmetricMerge|Symmetric Merge]] Wiki page.

----
= Complex Merging =
== Complex Merge Use Case ==
Line 54: Line 63:

(This question is based on the premise that the merge from A to A_COPY will be executed by selecting a set of revisions along the direct history of branch A, and merging them to branch A_COPY. This is what the merge algorithm does in Subversion v1.5 through at least v1.8 (except when reintegrating). A different merge algorithm might be needed to handle this scenario well.)

The section on keeping a reintegrated branch alive became obsolete with the release of Subversion 1.8.


Keeping a Reintegrated Branch Alive

A discussion on ways to improve the user experience when trying to keep using a branch after reintegrating it. This was a problem from Subversion 1.5 through Subversion 1.7. See "Keeping a Reintegrated Branch Alive" in the Subversion 1.6 Book here: http://svnbook.red-bean.com/en/1.6/svn-book.html#svn.branchmerge.advanced.reintegratetwice.

Simple Use Case

Here's a diagram showing a typical feature-branch work flow and the step we want to eliminate.

Rev

A

B

Commit

r10

X

r20

X

New branch B from A

r30

X

Modify B

r40

M

Reintegrate B to A

r45

R

Keep-alive record-only merge A@40 to B

r50

X

More work in A

r60

M

Sync merge A to B

The sync merge r60 should "take" the change r50 from A, but not r40. Subversion client versions 1.5 through 1.7 don't merge correctly at r60 without extra help such as that provided by the r45 commit.

Ways to make it easier

(in order from easiest to implement to best for the user):

  • Make it easier for the user to do the record-only dance: make 'svn merge' print the required command at the end of the merging. Perhaps store info in the WC and make 'svn commit' notice and at least print a reminder. Possibly even have 'svn commit' do that keep-alive commit after the regular commit. (With the current mergeinfo design it needs to be a separate commit because it needs to reference the rev number of the first commit.)
    svn merge --reintegrate ^/branches/this-branch trunk-wc
    --- Merging ...
    [...]
    To continue using the source branch after this reintegration, note the
    new revision number REV created by the commit and perform the following
    command in a working copy of that branch:
    
      svn merge --record-only --change REV ^/trunk .
  • Provide some way for the user to mark a revision as merged without requiring a working copy. I'm not suggesting to tell people to 'svn propedit' the svn:mergeinfo property directly, but to have a way to achieve the desired effect with 'svn merge'. For instance, we could allow --record-only merges on URL targets. [Idea from stsp.]
  • Make the reintegrate command optionally commit the result if there are no conflicts (which is typically the case, if the branch was up to date and the trunk isn't too busy). After the reintegrate command commits the reintegration, make it do the keep-alive commit directly in the repo. It would require a clean WC so that it knows this reintegration is the only thing it is committing. This would not allow running regression tests prior to commit.
    svn merge --reintegrate --commit ^/branches/this-branch trunk-wc
    --- Merging ...
    [...]
    --- Committing ...
    [...]
    Committed revision 1234.
    --- Committing a mergeinfo adjustment to keep the source branch alive ...
    [...]
    Committed revision 1235.
  • Make a no-WC reintegrate command, that performs the reintegrate and commits it, and then does the record-only straight into the repo. This work-flow is possible because typically there should be no conflicts when reintegrating; bail out if there are. It might be hard without a WC, might need some Subversion library re-architecting.
  • Make the "sync merge" code recognize the reintegration revision without having to record-only it on the branch. Either store a special marker in the svn:mergeinfo at reintegrate time, or deduce the fact at sync-merge time. Difficult I know.

Subversion 1.8 implements a solution superior to any of the above. The enhancement is announced in the 1.8 release notes and some design notes are in the Symmetric Merge Wiki page.


Complex Merging

Complex Merge Use Case

In the final sync merge in this more general use case, the interesting question is what to do with r11.

(This question is based on the premise that the merge from A to A_COPY will be executed by selecting a set of revisions along the direct history of branch A, and merging them to branch A_COPY. This is what the merge algorithm does in Subversion v1.5 through at least v1.8 (except when reintegrating). A different merge algorithm might be needed to handle this scenario well.)

A@1---r4---r5---r6---r7----------------r11----------->
 |\                                     ^          |
 | \                                    |          |
 |  \                              reintegrate     |
 |   V                                  |          |
 |   A_COPY_2-----------------r9---r10---          |
 |                            ^                sync merge
 |                           /                     |
 |                  cherry-pick merge of r8        |
 V                         /                       V
 A_COPY-------------------r8------------------------->

We can see that part of r11 is "new" and should be merged (the part that came from r10), but another part of r11 is a change we already have (the part that came from r8). What are the options?

  1. Try to merge r11 into A_COPY (and record it as merged), accepting that (in principle) it will conflict.
  2. Don't merge r11 into A_COPY (and don't record it).
  3. Instead of taking r11 as a whole change, find its constituent parts and merge the required parts. Then record r11 as merged.
  4. Stop and report the problem.

Option (1) is the current (<=1.7) behaviour. Merging r11 will (in general) produce conflicts because the part of the change that originated as r8 will be re-played onto A_COPY which already has r8. Some of the conflicts might be "physical" conflicts, detected and reported by Subversion, while others might be automatically resolved by Subversion, while still others might be logical conflicts that cannot be detected automatically. Because we know that the merge will confilct (and can determine it algorithmically), we should at least display a diagnostic message that gives details of which change(s) being merged include some changes that are already present.

Option (2) leaves the user to decide whether and how to fill in the missing bits. Like option (1) we should at least display a diagnostic message that gives details. A disadvantage is that the revisions from the source branch end up being merged out of order: the current merge will proceed with the later revisions, and then if the user wants to merge the relevant parts of the skipped revision those parts will be merged later.

Option (3) could be done in several different ways. Examples:

  • Reverse-merge r8 from A_COPY and then merge r11.
  • Just merge r10 into A_COPY.
  • Reverse-merge r9 from a temporary copy of A@11 and then merge the resulting {r11 minus r9} into A_COPY.

The best way to perform this partial merge would depend on the relationships between the branches, such as how similar each one is to each other one. There is no single Right Way, and there is no way to perform such a merge that would never produce conflicts. Designing a partial-merge algorithm would advance the merge tracking capability into a significantly more sophisticated model.

Option (3) is too complex and so is not under consideration here.

Option (4) has the advantage that the user can take action such as performing other merges (especially onto the source or target branch of the interrupted merge) before continuing. This may be better than (2) because the source revisions would be merged in order.

I would propose that Subversion give users the ability to specify in advance or interactively what action to take when encountering a partially-merged revision. The backward-compatible default would be option (1) plus a diagnostic message. The options would be (1), (2) and (4).

KeepingReintegratedBranchAlive (last edited 2013-09-03 09:13:11 by JulianFoad)