unexpected tree conflict on merge for same source file
Hello, imagine the following repository structure: /branches/prj1/first.txt /branches/prj1/second.txt /branches/prj2/first.txt /branches/testing/first.txt /branches/testing/second.txt /trunk/first.txt All first.txt in /branches/* are from the same /trunk/first.txt The file was only changed in /trunk and synced in /branches/prj1/ prj1 was merged into testing Why is there a tree conflict when I try to merge prj2 into testing? It is the same file. Below is a .bat file for creating the repo with some more conflicts that we do not understand. I would be happy if someone could explain these as well. What I try to achieve with the additional testing branch is to have some kind of staging before going live. The idea is to do this for new features: 1. Create branch from the latest live system /(trunk) 2. Work on branch 3. Merge branch into testing system (/branches/testing) 4a If everything is ok merge into /trunk and delete branch 4b If something is wrong return to 2. Best regards Sven. @REM testsvn.bat cls svn --version @REM svn, Version 1.7.2 (r1207936) @pause svnadmin --version @REM svnadmin, Version 1.7.2 (r1207936) @pause D: cd \ mkdir test cd test svnadmin create repo svn checkout file:///D:/test/repo wc cd wc mkdir branches mkdir tags mkdir trunk svn add branches tags trunk svn commit -m "basic repo structure" svn switch --ignore-ancestry file:///D:/test/repo/trunk svn info @REM Working Copy Root Path: D:\test\wc @REM URL: file:///D:/test/repo/trunk @pause echo .>first.txt svn add first.txt svn commit -m "1st" svn copy -m "prj0" . "^/branches/prj0" svn copy -r HEAD -m "prj1" "^/trunk" "^/branches/prj1" svn switch "^/branches/prj1" echo .>second.txt svn add second.txt svn commit -m "2nd" svn switch "^/trunk" svn copy -r HEAD -m "testing" "^/trunk" "^/branches/testing" echo "change" > first.txt svn commit -m "change" svn copy -r HEAD -m "prj2" "^/trunk" "^/branches/prj2" echo "change2" > first.txt svn commit -m "change2" svn copy -m "prj3" . "^/branches/prj3" svn switch "^/branches/prj2" svn merge "^/branches/prj1" svn commit -m "prj1 into prj2" svn switch "^/branches/prj3" svn merge "^/branches/prj0" @REMC first.txt @REM --- Recording mergeinfo for merge of r2 through r11 into '.': @REM U . @pause svn st @REM M . @REM C first.txt @REM > local add, incoming add upon merge @pause svn revert -R . svn switch "^/branches/prj1" svn merge "^/trunk" svn commit -m "prj1 sync" svn switch "^/branches/testing" svn merge "^/branches/prj1" svn commit -m "prj1 into testing" svn merge "^/branches/prj2" @REM --- Recording mergeinfo for merge of r2 through r7 into '.': @REM U . @REM -- Zusammenfuehren von r8 bis r13 in '.': @REMC second.txt @REM G . @REM --- Recording mergeinfo for merge of r8 through r13 into '.': @REM U . @pause svn st @REM M . @REM C second.txt @REM > local add, incoming add upon merge @pause svn revert -R . cd \
Re: unexpected tree conflict on merge for same source file
Am 17.10.2012 12:00, schrieb Stefan Sperling: > On Tue, Oct 16, 2012 at 06:35:21PM +0200, Stefan Sperling wrote: >> Again, sticking to simple branching/merging patterns where all merges >> happen between directly related branches makes things a lot easier. > > Hi again Sven, > > I've looked at this some more trying to come up with a simpler solution. You are really into this problem. Thank you for your effort! :) > It turns out that the root of all evil really is the mixed-revision > copy you've made to create the first branch. If the branch is created > by copying URLs the add vs. add tree conflict problem disappears. As written in my first reply: The mixed-revision copies seem to be a problem with the usage of TortoiseSVN. I will check the next time when I create abranch using this 3rd party tool. > Also, a 2-URL merge is not strictly required to run the merge between > the two unrelated (or "cousin") branches. But you need to sync the > branch you're merging from to trunk first, which moves the common > ancestor point forward in history [...] > This requires a > record-only merge to work around the mixed-revisionness of the branch > but is otherwise straightforward. > > Below is a unix shell script I used to reproduce the problem. > See the comments inside the script for more details. > > svn add $trunk/foo > svn ci $trunk -m "add new file" > > # mixed-rev copy! > svn copy $trunk $branch1_url -m "creating branch 1" > # doing this instead would prevent tree conflicts below: > # svn copy $trunk_url $branch1_url -m "creating branch 1" Doing a "svn up" before the "svn copy" in the root of the working copy should the trick as well, right? > # sync branch1 to trunk, moving the common ancestor used for the merge > # beyond the creation of 'foo' to avoid the above tree conflict > # > > # r2 created 'foo' which exists on branch1 because of mixed-rev copy. > # Mark r2 as merged into branch1 to avoid another add vs. add tree-conflict. > svn up $branch1 > svn merge --record-only -c2 $trunk_url $branch1 Doing this requires that you know a lot about what happens in other branches. There could be hundreds of commits in each of the branches and trunk by multiple people over several month. Why is it not possible for SVN to see that the source files are the same and the trunk changed the contents that are now valid? See also my other mail for a similar question. Best regards Sven. PS: Sorry for cross referencing to other mails but I don't see an easy option to reply to multiple mails in one new mail.
Re: unexpected tree conflict on merge for same source file
Am 16.10.2012 18:02, schrieb Stefan Sperling: > On Tue, Oct 16, 2012 at 01:17:40PM +0200, Sven Uhlig wrote: >> Below is a .bat file for creating the repo with some more conflicts that >> we do not understand. I would be happy if someone could explain these as >> well. > > Please see my remarks below. Thank you to all your response! I didn't expect to get a in-depth answer this quickly - though I am very happy to see this rate of activity :) >> echo .>first.txt >> svn add first.txt >> svn commit -m "1st" >> >> svn copy -m "prj0" . "^/branches/prj0" > > You're copying a mixed-revision working copy here. > Is that really what you want? > ^/branches/prj0 is a copy of ^/trunk@1 > ^/branches/prj0/first.txt is a copy of ^/trunk/first.txt@2. > See > http://svnbook.red-bean.com/en/1.7/svn.basic.in-action.html#svn.basic.in-action.mixedrevs > You are right. That is not what I want. This was just a test to see if this will cause errors. Usually we use TortoiseSVN to do everything with SVN and it seems this is what happens behind the scenes of TSVN. I know this is the wrong list to discuss this topic. I will remove this from any further replies from me. >> svn switch "^/branches/prj2" >> svn merge "^/branches/prj1" > > prj1 is a branch off trunk, and so is prj2. > Which means prj1 and prj2 are not ancestrally related. But they have the same ancestry, at least the same directory, may be not the same revision. This is ok for my understanding. > 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. >> svn switch "^/branches/prj1" >> svn merge "^/trunk" >> svn commit -m "prj1 sync" > > What is the purpose of this sync merge? This is to sync the branch with the changes from trunk. For me it looks like how it is done in the SVN book. http://svnbook.red-bean.com/nightly/en/svn.branchmerge.basicmerging.html#svn.branchemerge.basicmerging.stayinsync >> 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/) > What is the purpose of the separate 'testing' branch? Why are you not > testing prj1 directly, reintegrate it into trunk when tests succeed, > and then sync all your other branches to trunk to merge prj1 changes > into them? The tests are made in the branches directly at first. After that the changes are merged to the testing branch to check how it looks like with all the other changes in development. The whole project is for a website. Because there are so many small changes that do not need a real independet branch, there is a generic development branch "testing" and there are no version tags. When the small changes are OK, they are merged to trunk which represents the live server. (instead of tags) Changes that are not OK, may get reverted or updated later. > If you did that, your approach of using 'svn merge ^/some-branch' > would work fine. But make sure to use the --reintegrate option whenever > you merge one of your branches back into trunk (fortunately, the requirement > to use --reintegrate will go away in Subversion 1.8, but for now you must > still use it). See above: Reintegration is not an option because the development will continue on both branches in parallel. > See the output of 'svn help merge' for more details. It has some diagrams > to illustrate which 'svn merge' invocation is appropriate for a given > merge scenario. It seems there is no such scenario documented until now ;) > If you really must merge between unrelated branches, use the 2-URL > merge syntax This seems to be the only solution - before looking at your third e-mail from today, 10:00 GMT. So the only open question in this mail is the conflict regarding second.txt and the merge into /branches/testing/. Best regards Sven.
Re: unexpected tree conflict on merge for same source file
Am 17.10.2012 19:12, schrieb Stefan Sperling: > On Wed, Oct 17, 2012 at 05:30:14PM +0200, Sven Uhlig wrote: >> 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. For me it sounds like the "Keep Alive Dance". (See also the very bottom of this mail.) > 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? Sometimes only a small part of the changes in branch A is needed in branch B because the ideas evolve for branch B. Usually I isolate branches as suggested. > 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. Yes, it makes merging more difficult. But that is what cherry-pick and svn:mergeinfo are for? svn:mergeinfo has all the required information if it looks into the past. > In your case, why are the branches which need to share common code not > branches off a branch which contains the shared code? At the time when the branches were created there was no use of shared code. Later some functions seem to be unexpectedly usefull in the other branch. > 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. I think externals are not the right solutions if only single files or even only some lines of source code are to be shared. >> >> 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". >> >> 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) > [no mergeinfo addition for prj1 see Stefan Sperlings 2nd mail] > [old merginfo: Merged prj1:40-60, see previous merge] > 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'. Just before the conflict in r71 the paths for second.txt to it's original source (using your revisions) look like this: 1. prj1/second.txt@40 is the original file 2. prj2/second.txt@50 comes from prj1/second.txt@49 3. testing/second.txt@61 comes from prj1/second.txt@60 When merging prj2/ into testing, then
Re: unexpected tree conflict on merge for same source file
Am 18.10.2012 15:06, schrieb Stefan Sperling: > On Thu, Oct 18, 2012 at 02:10:25PM +0200, Sven Uhlig wrote: >> Am 17.10.2012 19:12, schrieb Stefan Sperling: >> At the time when the branches were created there was no use of shared >> code. Later some functions seem to be unexpectedly usefull in the other >> branch. > > That happens and is sometimes not avoidable, but it also indicates poor > planning and/or developer coordination. [...] > It sounds > like it is an exceptional circumstance, which means we're not talking > about a problem you are hitting often, which is good. Is that correct? It is an exception. But I am afraid that this can happen at any time again. > And don't get me wrong, I'm just describing how Subversion works to > explain why you are seeing conflicts. I'm not saying these spurious > conflicts are a good thing. It is good that you have said that. I was not sure if you didn't understand the problem or if you are just describing SVN's behaviour. So you do understand and you are just describing - that's fine. >> I think that SVN records the wrong revisions for mergeinfo or copy >> because the file was not changed since addition but SVN still remembers >> a newer revision than the latest change and thus sees a conflict/difference. > > It doesn't record wrong information in the sense that the information > is inaccurate. My idea was that if SVN recorded other revisions or information then may be SVN could see that it is the same file. > Yes, there are some nice improvements coming in 1.8. But I don't > think the spurious add vs. add conflict we're talking about will be > automatically resolved in 1.8. Maybe in 1.9 or later. > We're currently still working on more basic problems in this area. Well, there are work-arounds available. If everyone knows them, and if everyone knows that there will be improvements at some time, then everything is fine. Unfortunately 1.9 is far away in the future :( > Reporting issues like this helps us to see what kinds of tree conflicts > people are hitting in practice. Before I posted to this list, I used Google to find similar issues and I did. So I was not sure if you'll accept yet another question for the same SVN error message. I'm glad to see that you still reply :) > This is very valuable and helps the project. > And more help is always welcome, if you're interested :) I'm not sure if I understand the last part "if you're interested." Do you mean help as active member of the mailing list, as a tester/bug reporter or help as a developer? Best regards Sven. PS: Sorry for the late reply.
Re: Need to restructure repo folders: Problem: SVN COPY is recursive
Am 15.03.2013 21:30, schrieb tim.willi...@ucb.com: > Yes, it appears I am headed toward a wrapper script to copy one file at a > time. I wanted to make sure I was not missing something in SVN that would > make it easier (a non-recursive copy, or something in svnmucc where I could > copy a bunch a files and commit them all in a single new revision, for > example). > > It appears that I am stuck creating a new revision for every single file I > need to move. This will make the SVN Log history long and boring, but it > appears there is not much else that can be done if my users want to retain > the development history. Otherwise I would just SVN export it, remap it in a > work area and commit it all in "one big go." > I dont think you have to create a new revision for each single file. Just do svn copy and then do a svn delete for all files that you dont want to have copied. e.g. svn copy /foo/bar /new svn delete /new/bar/baz svn copy /foo/qwx /new/bar svn delete /new/bar/qwx/abc ... svn commit