[cvsnt] Re: Branch merging - this seems wrong...

Gerhard Fiedler lists at connectionbrazil.com
Wed Jun 7 13:30:28 BST 2006


Andreas Krey wrote:

> On Wed, 07 Jun 2006 11:23:54 +0000, Tony Hoyle wrote:
>> Tony Eva wrote:
>>>No - the changes in B1 are not lost.  B2 is not just a copy of A3, it is
>>>a merged sum of B1 and A3.
>>
>> No it isn't.  B2 is simply the changes required to go from B1 to the merged
>> B1+A3.  Similarly B3 does not contain B2.
> 
> Somehow I should really have used revision numbers instead of An and Bn
> to make absolutely clear that these are committed revisions, not some
> diffs.
> 
> B2 ist the *result* of the merge of B1 and A3, thus all changes
> on the way A1->(B0)->B1 *and* all changes on the way A1->A2->A3
> are present in the revision B2, plus what was needed to resolve
> conflicts.

Yes, B2 of course /contains/ all desired changes, but that's not what merge
points are about. Neither are merge points about common ancestors. Merge
points are about /differences/. 

If you say "use B2 as merge point for the final merge of B3 into A(4)",
this is equivalent to saying "merge the difference from B2 to B3 into A(4)"
-- which obviously isn't what you want.

Merge points work just fine, though, for all the successive merges from A
to B. Say you merge A2 into B. This merges the change set A2-A1 into B and
creates a merge point at A2 for branch B. Then you merge A3 into B. This
merges the change set A3-A2 into B (because A2 is the most recent merge
point for B on A) and creates another merge point at A3 for branch B. And
so on.

> For reference:
> 
>     A
>     |
>     A1------>B0    # Set branch B on version A1 (B0 is the same as A1)
>     |        |
>     A2       |
>     |        B1    # Independent work
>     A3       |
>     |        |
>     *------->B2    # Merge A up to A3 into B (and commit)
>     |        |
>     A4       B3    # More independent work


I really think that both approaches (Tony Hoyle's comments about merge
points and our need to have temporary development branches that stay in
sync with the main development branch) converge in my suggestion to only
merge from A to B, and after the final merge from A to B, /copy/ B to A.

This way, merge points work as they should: all merges are from A to B, and
cvsnt uses merge points to "remember" where you last merged A into B. At
the end, after the final merge from A to B, the tip of B contains exactly
the code that should be on A at this point: all changes committed to A
since the root of B (A1/B0) are there, plus the complete implementation of
the feature B. So -- just take this code and put it on A, without merging.
Due to having merged in /all/ changes from A (and this is of course
crucial!), there is no need to /merge/ B back to A; this is a copy.

When I say "copy", it's of course not a simple file copy :) Use a directory
diff, and 
1- copy all files that are different from B to A
2- copy all files that are on B but not on A from B to A and add them there
3- remove all files from A that are on A but not on B
4- commit A.

This kind of looks like a merge, but it isn't, conceptually. It's simply
making the tip of A identical to the tip of B.


I think the whole problem was trying to use a merge (for the final merge of
B back to A) where no merge should happen because this is, conceptually, a
copy, not a merge. There is nothing to merge back, because B contains
exactly the desired code. What you might want here is a "branch copy"
command, but that can easily be done with a script. 

Gerhard



More information about the cvsnt mailing list