On Wed, Mar 07, 2012 at 03:47:31PM +0100, Erik Andersson wrote: > I'm a svnmerge.py user, trying to understand core svn merging. > > If creating branches from trunk, you cannot have two release branches and > keeping the release branches alive with reintegrate? > > When the second release branch is merged to the trunk, the first release > branch can no longer be merged to trunk with reintegrate because then the > content from the second release branch will be removed from the trunk if > you reintegrate the first branch with trunk. > > I hope this script example explains it: > http://paste.pocoo.org/show/260265/ > > I would really appreciate any feedback on this.
If I understand your example correctly, you want to do the following: - make changes on the 1.0 release and merge these changes to 1.1 and trunk - make changes on the 1.1 release and merge these changes to trunk - eventually create a 1.2 release from trunk -- this release is a superset of 1.0 and 1.2. What I don't understand is why you try to reintegrate branch 1.0 into trunk while no real changes were made on the 1.0 branch since the previous merge. You do "work" on the 1.0 branch at the very start of your script, but no additional work is ever done again before you merge the 1.0 branch to trunk a second time. Is this an oversight or did you just intend to keep the example short? As written, the script shows the problem you are pointing out quite well, but it doesn't really make sense in terms of a sensible merge strategy and therefore I am not sure what your intentions really are. What I don't understand is if you intend to make commits that are unique to trunk, i.e. neither in 1.0 and 1.1. Are you syncing the 1.0 branch to trunk in r7 in your example because trunk might have changes that should be merged to 1.0, or simply because the svnbook recommends to perform a sync before reintegration? If you make changes to both trunk and 1.0 in parallel and keep syncing both branches to one another, what's the point of having the 1.0 branch in the first place? Maybe trunk never receives non-merge commits and you'd create a 1.2 branch from trunk as soon as you want to make a change that isn't suitable for 1.0 and 1.1? In this case, you could use a stair-case branching model instead of forking release branches off trunk: 1.2 +--------------- | 1.1 +------+--------------- | 1.0 ------+---------------------- So you'd have no trunk at all. To prepare a new release the previous release is copied to a new branch with an incremented version number. What you would do now is always merge changes made on a branch upwards to the next level, e.g. a bug fixed in 1.0 would be merged to 1.1 and 1.2 in two steps: cd 1.1-working-copy; svn merge ^/1.0; svn commit cd 1.2-working-copy; svn merge ^/1.1; svn commit You can also block revisions from being merged upwards using --record-only merges in this model, like you do in your example. It is also easier to visualise the flow of changes. However, it requires that bugs are always first fixed in the oldest affected and maintained release. If you'd like to keep branching releases off trunk as you do in your script, --reintegrate is not what you need. Instead, you can regard your merges from release branches to trunk as giant cherry-picking merges. The release branches are never reintegrated to trunk. Which means that you merge as you do in your example script, but remove the --reintegrate option from your merge commands. If I modify your script accordingly (diff below), the problem you see with the final reintegrate merge goes away. It's quite possible that this is the real equivalent of what svnmerge.py actually did. It is possible that this approach leads to unnecessary conflicts in practice. I'm not quite sure if that will be the case because of the unknown aspects of your overall merge strategy. Following the flow of change also is a bit harder than in the stair-case model. So I'd recommend to consider a switch to the stair-case model if it is applicable to your situation. --- 260265-orig.sh Wed Mar 7 19:57:32 2012 +++ 260265.sh Wed Mar 7 20:02:57 2012 @@ -59,7 +59,7 @@ # Reintegrate branch1_0 svn up $trunk -svn merge --reintegrate $branch1_0_url $trunk +svn merge $branch1_0_url $trunk svn ci $trunk -m "reintegrate 1.0 branch into trunk" # Keep 1.0 branch alive, we need to do more work still. @@ -75,7 +75,7 @@ # Reintegrate 1.1 branch svn up $trunk -svn merge --reintegrate $branch1_1_url $trunk +svn merge $branch1_1_url $trunk svn ci $trunk -m "reintegrate 1.1 branch into trunk" # We don't want this changeset merged to an older release. @@ -96,7 +96,7 @@ # Now, if I try to reintegrate branch1_0 to trunk I will get in trouble.. svn up $trunk -svn merge --reintegrate $branch1_0_url $trunk +svn merge $branch1_0_url $trunk svn diff $trunk # the changes commited in 1.1 branch is reverted since it doesn't exist in