On Wed, Oct 17, 2012 at 05:30:14PM +0200, Sven Uhlig wrote: > > Ideally, you'd reintegrate prj1 into trunk first and then merge the > > changes into prj2 from trunk, using a sequence such as: > > I guess this merge was a bad example and wrong as well. There could be > changes that are commited to prj1 that are requried in prj2 because of > e.g. some shared code. > > I would do this with the following command: > svn merge -r A:B "^/branches/prj1" > > Reintegration is not an option because the development will continue on > both branches in parallel.
This approach sounds very chaotic to me. Usually you'd isolate branches from another precisely because each branch should *not* see code developed on the other cousin branches. But at the same time you want these branches to share some code? That's a contradicition. And it makes merging harder than it needs to be. Every time you cherry-pick changes between cousins you run a high risk of merge conflicts later when the cousins are merged into other branches. I mean, what you're doing is: svn copy ^/trunk ^/branches/branch1 svn copy ^/trunk ^/branches/branch2 Usually, branch1 should never see code from branch2 and vice versa. Unless one of the branches gets reintegrated into trunk, in which case changes are transferred between the branches indirectly via merges to and from trunk. That's the whole point of having two distinct branches. In your case, why are the branches which need to share common code not branches off a branch which contains the shared code? Something like: svn copy ^/trunk ^/branches/shared-base-branch svn copy ^/branches/shared-base-branch ^/branches/branch1 svn copy ^/branches/shared-base-branch ^/branches/branch2 Now you can develop common code on shared-base-branch, and changes specific to branch1 and branch2 on each of those branches, respectively. The flow of change is straightforward: Branch1 and branch2 only sync to the shared-base-branch, which in turn syncs itself to trunk. The shared-base-branch can be reintegrated into trunk once both branch1 and branch2 have been reintegrated into it. This eliminates cherry-picking, thereby reducing the risk of merge conflicts, and it also makes it easier to figure out which changes have already been merged where. If the above won't work for some reason, maybe you shouldn't be using branching/merging in the first place. Instead, you could treat the shared code as an external dependency which your build system will pull into the build. Pushing the problem out of the version control problem space into the build system problem space can make sharing code a lot easier to manage. You could also consider using an svn:external to pull the same shared code into a subdirectory of each branch, instead of cherry-picking changes between cousin branches. > >> svn switch "^/branches/testing" > >> svn merge "^/branches/prj1" > >> svn commit -m "prj1 into testing" > >> > >> svn merge "^/branches/prj2" > > > > Again, you hit a similar problem here. > > I do not understand why there is a conflict in "second.txt". > > As far as I can see it the following files are the same: > - /branch/prj1/second.txt > - /branch/prj2/second.txt > > /branch/prj1/second.txt was added and never changed > > svn switch "^/branches/prj1" > > svn add second.txt > > svn commit -m "2nd" > > /branch/prj2/second.txt was also added and never changed > > svn switch "^/branches/prj2" > > svn merge "^/branches/prj1" > > svn commit -m "prj1 into prj2" > > With svn:mergeinfo the SVN should have enough information to see that > the files are the same. There was no change and the original source is > the same (/branches/prj1/) You created second.txt on the prj1 branch. Let's assume you did so in revision 40, so that the change within prj1@40 looks like this: A second.txt ("add a file called second.txt") You then cherry-picked this revision from prj1 into prj2, causing a commit that added second.txt to prj2. Let's call this changeset 'prj2@50': A second.txt (copied from, say, prj1@49) Mergeinfo addition: Merged prj1:40-49 Now you merge prj1 into testing, let's say in r61. The common ancestor of testing and prj1 is trunk, which does not contain second.txt. So among other changes you are merging: A second.txt (copied from, say, prj1@60) Mergeinfo addition: Merged prj1:40-60 Next, you merge prj2 into testing, let's say in r71. The common ancestor of prj2 and testing is trunk, which does not contain second.txt. So the changeset being merged looks something like this: A second.txt (copied from, say, prj2@70) Mergeinfo addition: Merged prj1:61-70 Mergeinfo addition: Merged prj2:50-70 This results in the add vs. add tree conflict. How is Subversion supposed to tell that prj1:40-70 contains the same semantic change as prj2:50-70, the change which we cherry-picked from prj1 to prj2? In terms of mergeinfo the addition of second.txt happens in two distinct changesets: prj1@40 and prj2@50 Mergeinfo doesn't tell us that, semantically, prj1@40 and prj2@50 contain the same change. And neither does tracing back history to the common ancestor of prj2 and testing tell us that these 'second.txt' files are related. The common ancestor is trunk, which has never seen 'second.txt'. The fact that this is a spurious conflict is evident to us because we know how the second.txt addition to prj2 came about. But what if we had added a different 'second.txt' file to prj2, which just happens to have the same name but is otherwise unrelated to the existing file in testing and prj1? Subversion cannot tell the difference between this scenario and the one above, so it needs to flag a tree conflict to alert us of the possibility that there is a genuine tree conflict. One key aspect here is that Subversion treats addition as a first-class operation. It doesn't care what the content of a newly added file is. If the change you are merging contains an 'A foo' change, that means "add foo", regardless of foo's content.