Christophe Royer wrote on Sat, 14 May 2022 23:28 +00:00:
> Thank you for looking into this, taking the time to clean up the script 
> and share your comments. Lessons learnt.
>
> I will likely revert (maybe manually) those invalid mergeinfo.
>

Sure.  I recommend that you use a record-only reverse merge, as opposed
to a propedit.  The latter could cause rather a lot more fun if you
commit a syntax error to the repository.

> Still not quite sure of the consequences, and if this situation could be 
> detected. Maybe a defect or enhancement should be logged - but I am not 
> familiar how this done.
>

See <https://subversion.apache.org/reporting-issues.html>.  You've
already posted a thread and gotten someone to validate/buddy your
complaint (me, hereby), so feel free to submit an issue.

If you wish, you can wait a day or two before filing anything, in case
any of the other devs respond to my previous post with the analysis and
the specific question.

> Thanks again.
>

You're welcome.

Daniel

> Christophe
>
> On 5/14/2022 5:39 AM, Daniel Shahaf wrote:
>> Christophe Royer wrote on Fri, May 13, 2022 at 10:45:14 -0700:
>>> Daniel, the first script I sent may confuse things a little, because of the
>>> tree conflict.
>>> Here is another script that avoid that issue. The problem is the same: it
>>> looks like the mergeinfo does not match the state of the branch.
>> 
>> [ There's a longish preface here about the reproduction script and its
>> output.  For Christophe's mergeinfo-related question, skip the
>> triple-braced part. ]
>> 
>> {{{
>> Here's a Unix version of your script:
>> 
>> [[[
>> #!/usr/bin/env zsh
>> alias '@ECHO'=: REM=: ECHO.=echo ECHO=echo md=mkdir SET='() { 
>> repoRoot=file://$PWD/repo }' TYPE=cat
>> rd() { rm -rf -- ${argv:#/*} }
>> s="$(< script.bat tr '\\' '/' | sed -e 's/%repoRoot%/$repoRoot/g' -e 
>> 's/FileA/fileA/g' -e 's/FileB/fileB/g' | perl -C -Mutf8 -pE $'y/()\'"/{}’”/ 
>> if /ECHO|REM/')"
>> setopt ignorebraces
>> set -ex
>> eval "$s"
>> ]]]
>> 
>> That assumes ./script.bat contains the script you posted, without the
>> delimiter lines.  It's written as a dense multilingual mix because it
>> doesn't need to be team-maintained indefinitely going forward, so I
>> optimized for whatever was fastest to implement.  It'd be fairly easy to
>> port that to sh if need be.
>> 
>> Also, it would also have been helpful if you hadn't used different
>> letter cases to refer to a single on-disk file, to make it easier to
>> port the script; if the script began by deleting ./repo ./WC
>> ./workingCopy, so it would be easier to re-run it; and if the script had
>> been attached rather than inlined, because long lines were hard-wrapped
>> along the way; and if you'd posted your script's _output_ as well as its
>> code, so those of us on other platforms would be able to analyze the
>> script without porting it first.  Anyway, no harm done.
>> 
>> Here's the script's output:
>> 
>>> +(eval):1> : off
>>> +(eval):2> : -- Script to test handling of merge info during a 2-url merge
>>> +(eval):3> : -- this time, we setup to avoid tree conflict: we don’t add 
>>> file after the branches are created,
>>> +(eval):4> : -- we just update them
>>> +(eval):7> : script.bat script.zsh
>>> +(eval):8> : 2 files in trunk: fileA and fileB
>>> +(eval):9> : 2 branches
>>> +(eval):10> : edit fileA in trunk, merge to foo
>>> +(eval):11> : edit fileB in foo
>>> +(eval):12> : diff between trunk and foo do NOT show fileA '{merged,' same 
>>> im 'both}'
>>> +(eval):13> : 2-url merge trunk to foo into bar: should bring changes to 
>>> fileB only
>>> +(eval):14> : script.bat script.zsh
>>> +(eval):17> echo
>>>
>>> +(eval):18> echo -- Create empty repo in current folder
>>> -- Create empty repo in current folder
>>> +(eval):19> mkdir repo
>>> +(eval):20> svnadmin create --fs-type fsfs repo/testRepo
>>> +(eval):22> '(anon)' 'repoRoot=file:///%CD:/=/%/repo'
>>> +(anon):0> repoRoot=file:///scratch/tmp.9SbJ9D2q2o/repo
>>> +(eval):24> echo
>>>
>>> +(eval):25> echo -- Create sructure to import in repo
>>> -- Create sructure to import in repo
>>> +(eval):26> mkdir WC
>>> +(eval):27> mkdir WC/trunk
>>> +(eval):28> mkdir WC/branches
>>> +(eval):29> svn import WC file:///scratch/tmp.9SbJ9D2q2o/repo/testRepo 
>>> -mImporting
>>> Adding         WC/branches
>>> Adding         WC/trunk
>>> Committing transaction...
>>> Committed revision 1.
>>> +(eval):30> rd /s /Q WC
>>> +rd:0> rm -rf -- WC
>>> +(eval):32> echo
>>>
>>> +(eval):33> echo -- Check out working copy of the entire repo
>>> -- Check out working copy of the entire repo
>>> +(eval):34> svn co file:///scratch/tmp.9SbJ9D2q2o/repo/testRepo workingCopy
>>> A    workingCopy/branches
>>> A    workingCopy/trunk
>>> Checked out revision 1.
>>> +(eval):36> echo
>>>
>>> +(eval):37> echo -- Play in trunk, adding two files
>>> -- Play in trunk, adding two files
>>> +(eval):38> pushd workingCopy/trunk
>>> +(eval):39> echo Adding fileA in trunk
>>> +(eval):40> echo Adding fileB in trunk
>>> +(eval):41> svn add fileA.txt fileB.txt
>>> A         fileA.txt
>>> A         fileB.txt
>>> +(eval):42> svn commit . '-mAdding 2 files to trunk'
>>> Adding         fileA.txt
>>> Adding         fileB.txt
>>> Transmitting file data ..done
>>> Committing transaction...
>>> Committed revision 2.
>>> +(eval):43> popd
>>> +(eval):45> echo
>>>
>>> +(eval):46> echo -- Create 2 branches from trunk. This does not create any 
>>> mergeinfo
>>> -- Create 2 branches from trunk. This does not create any mergeinfo
>>> +(eval):47> svn copy file:///scratch/tmp.9SbJ9D2q2o/repo/testRepo/trunk 
>>> file:///scratch/tmp.9SbJ9D2q2o/repo/testRepo/branches/foo '-mbranching to 
>>> foo' --parents
>>> Committing transaction...
>>> Committed revision 3.
>>> +(eval):48> svn copy file:///scratch/tmp.9SbJ9D2q2o/repo/testRepo/trunk 
>>> file:///scratch/tmp.9SbJ9D2q2o/repo/testRepo/branches/bar '-mbranching to 
>>> bar' --parents
>>> Committing transaction...
>>> Committed revision 4.
>>> +(eval):50> echo
>>>
>>> +(eval):51> echo -- Edit fileA in trunk
>>> -- Edit fileA in trunk
>>> +(eval):52> svn update workingCopy
>>> Updating 'workingCopy':
>>> A    workingCopy/branches/bar
>>> A    workingCopy/branches/bar/fileA.txt
>>> A    workingCopy/branches/bar/fileB.txt
>>> A    workingCopy/branches/foo
>>> A    workingCopy/branches/foo/fileA.txt
>>> A    workingCopy/branches/foo/fileB.txt
>>> Updated to revision 4.
>>> +(eval):53> pushd workingCopy/trunk
>>> +(eval):54> echo Editing fileA in trunk
>>> +(eval):55> svn commit . '-mEditing fileA in trunk'
>>> Sending        fileA.txt
>>> Transmitting file data .done
>>> Committing transaction...
>>> Committed revision 5.
>>> +(eval):56> popd
>>> +(eval):57> svn update workingCopy
>>> Updating 'workingCopy':
>>> At revision 5.
>>> +(eval):59> echo
>>>
>>> +(eval):60> echo -- Merge latest from trunk to foo. This creates mergeinfo 
>>> in foo and brings fileA changes
>>> -- Merge latest from trunk to foo. This creates mergeinfo in foo and brings 
>>> fileA changes
>>> +(eval):61> svn merge file:///scratch/tmp.9SbJ9D2q2o/repo/testRepo/trunk 
>>> workingCopy/branches/foo
>>> --- Merging r3 through r5 into 'workingCopy/branches/foo':
>>> U    workingCopy/branches/foo/fileA.txt
>>> --- Recording mergeinfo for merge of r3 through r5 into 
>>> 'workingCopy/branches/foo':
>>>   U   workingCopy/branches/foo
>>> +(eval):62> svn commit workingCopy/branches/foo '-mMerging latest from 
>>> trunk to foo'
>>> Sending        workingCopy/branches/foo
>>> Sending        workingCopy/branches/foo/fileA.txt
>>> Transmitting file data .done
>>> Committing transaction...
>>> Committed revision 6.
>>> +(eval):63> svn update workingCopy
>>> Updating 'workingCopy':
>>> At revision 6.
>>> +(eval):65> echo
>>>
>>> +(eval):66> echo -- Edit fileB in foo
>>> -- Edit fileB in foo
>>> +(eval):67> svn update workingCopy
>>> Updating 'workingCopy':
>>> At revision 6.
>>> +(eval):68> pushd workingCopy/branches/foo
>>> +(eval):69> echo Editing fileB in foo
>>> +(eval):70> svn commit . '-mEditing fileB in foo'
>>> Sending        fileB.txt
>>> Transmitting file data .done
>>> Committing transaction...
>>> Committed revision 7.
>>> +(eval):71> popd
>>> +(eval):72> svn update workingCopy
>>> Updating 'workingCopy':
>>> At revision 7.
>>> +(eval):75> echo
>>>
>>> +(eval):76> echo -- Perform 2-URL merge to get diff between trunk and foo 
>>> and apply to bar
>>> -- Perform 2-URL merge to get diff between trunk and foo and apply to bar
>>> +(eval):77> echo
>>>
>>> +(eval):78> echo -- Showing the diff first: fileA is not listed '{only' 
>>> 'fileB}'
>>> -- Showing the diff first: fileA is not listed {only fileB}
>>> +(eval):79> svn diff file:///scratch/tmp.9SbJ9D2q2o/repo/testRepo/trunk 
>>> file:///scratch/tmp.9SbJ9D2q2o/repo/testRepo/branches/foo
>>> Index: fileB.txt
>>> ===================================================================
>>> --- fileB.txt       (.../trunk)     (revision 7)
>>> +++ fileB.txt       (.../branches/foo)      (revision 7)
>>> @@ -1 +1,2 @@
>>>   Adding fileB in trunk
>>> +Editing fileB in foo
>>> Index: .
>>> ===================================================================
>>> --- .       (.../trunk)     (revision 7)
>>> +++ .       (.../branches/foo)      (revision 7)
>>>
>>> Property changes on: .
>>> ___________________________________________________________________
>>> Added: svn:mergeinfo
>>> ## -0,0 +0,1 ##
>>>     Merged /trunk:r3-5
>>> +(eval):80> echo
>>>
>>> +(eval):82> echo -- Now merging
>>> -- Now merging
>>> +(eval):83> svn merge file:///scratch/tmp.9SbJ9D2q2o/repo/testRepo/trunk 
>>> file:///scratch/tmp.9SbJ9D2q2o/repo/testRepo/branches/foo 
>>> workingCopy/branches/bar
>>> --- Merging differences between repository URLs into 
>>> 'workingCopy/branches/bar':
>>> U    workingCopy/branches/bar/fileB.txt
>>>   U   workingCopy/branches/bar
>>> --- Recording mergeinfo for merge between repository URLs into 
>>> 'workingCopy/branches/bar':
>>>   G   workingCopy/branches/bar
>>> +(eval):84> svn commit workingCopy/branches/bar '-mMerging diff from trunk 
>>> to foo into bar'
>>> Sending        workingCopy/branches/bar
>>> Sending        workingCopy/branches/bar/fileB.txt
>>> Transmitting file data .done
>>> Committing transaction...
>>> Committed revision 8.
>>> +(eval):85> svn update workingCopy
>>> Updating 'workingCopy':
>>> At revision 8.
>>> +(eval):87> echo
>>>
>>> +(eval):88> echo -- In bar, fileA does not have the trunk changes, good
>>> -- In bar, fileA does not have the trunk changes, good
>>> +(eval):89> cat workingCopy/branches/bar/fileA.txt
>>> Adding fileA in trunk
>>> +(eval):91> echo
>>>
>>> +(eval):92> echo -- But the trunk revision where fileA was changed '{r5}' 
>>> shows as merged in bar
>>> -- But the trunk revision where fileA was changed {r5} shows as merged in 
>>> bar
>>> +(eval):93> echo -- rev5 of fileA in the trunk
>>> -- rev5 of fileA in the trunk
>>> +(eval):94> svn cat 
>>> file:///scratch/tmp.9SbJ9D2q2o/repo/testRepo/trunk/fileA.txt@5
>>> Adding fileA in trunk
>>> Editing fileA in trunk
>>> +(eval):97> echo
>>>
>>> +(eval):98> echo -- mergeinfo porperty for bar
>>> -- mergeinfo porperty for bar
>>> +(eval):99> svn pg svn:mergeinfo workingCopy/branches/bar
>>> /branches/foo:3-7
>>> /trunk:4-5
>>> +(eval):100> echo
>>>
>>> +(eval):101> echo -- svn mergeinfo between trunk and bar
>>> -- svn mergeinfo between trunk and bar
>>> +(eval):102> svn mergeinfo workingCopy/trunk workingCopy/branches/bar
>>>      youngest common ancestor
>>>      |         last full merge
>>>      |         |        tip of branch
>>>      |         |        |         repository path
>>>
>>>      3         5        8
>>>      |         |        |
>>>    -------| |------------         trunk
>>>       \         \
>>>        \         \
>>>         --| |------------         branches/bar
>>>                         |
>>>                         WC
>> 
>> And 'log -v' of the resulting repository:
>> 
>>> ------------------------------------------------------------------------
>>> r8 | daniel | 2022-05-14 11:55:46 +0000 (Sat, 14 May 2022) | 1 line
>>> Changed paths:
>>>     M /branches/bar
>>>     M /branches/bar/fileB.txt
>>>
>>> Merging diff from trunk to foo into bar
>>> ------------------------------------------------------------------------
>>> r7 | daniel | 2022-05-14 11:55:46 +0000 (Sat, 14 May 2022) | 1 line
>>> Changed paths:
>>>     M /branches/foo/fileB.txt
>>>
>>> Editing fileB in foo
>>> ------------------------------------------------------------------------
>>> r6 | daniel | 2022-05-14 11:55:46 +0000 (Sat, 14 May 2022) | 1 line
>>> Changed paths:
>>>     M /branches/foo
>>>     M /branches/foo/fileA.txt
>>>
>>> Merging latest from trunk to foo
>>> ------------------------------------------------------------------------
>>> r5 | daniel | 2022-05-14 11:55:46 +0000 (Sat, 14 May 2022) | 1 line
>>> Changed paths:
>>>     M /trunk/fileA.txt
>>>
>>> Editing fileA in trunk
>>> ------------------------------------------------------------------------
>>> r4 | daniel | 2022-05-14 11:55:46 +0000 (Sat, 14 May 2022) | 1 line
>>> Changed paths:
>>>     A /branches/bar (from /trunk:3)
>>>
>>> branching to bar
>>> ------------------------------------------------------------------------
>>> r3 | daniel | 2022-05-14 11:55:46 +0000 (Sat, 14 May 2022) | 1 line
>>> Changed paths:
>>>     A /branches/foo (from /trunk:2)
>>>
>>> branching to foo
>>> ------------------------------------------------------------------------
>>> r2 | daniel | 2022-05-14 11:55:46 +0000 (Sat, 14 May 2022) | 1 line
>>> Changed paths:
>>>     A /trunk/fileA.txt
>>>     A /trunk/fileB.txt
>>>
>>> Adding 2 files to trunk
>>> ------------------------------------------------------------------------
>>> r1 | daniel | 2022-05-14 11:55:46 +0000 (Sat, 14 May 2022) | 1 line
>>> Changed paths:
>>>     A /branches
>>>     A /trunk
>>>
>>> Importing
>>> ------------------------------------------------------------------------
>> }}}
>> 
>> So, here's r8:
>> 
>> [[[
>> % cd workingCopy
>> % svn di -c 8
>> Index: branches/bar/fileB.txt
>> ===================================================================
>> --- branches/bar/fileB.txt      (revision 7)
>> +++ branches/bar/fileB.txt      (revision 8)
>> @@ -1 +1,2 @@
>>   Adding fileB in trunk
>> +Editing fileB in foo
>> Index: branches/bar
>> ===================================================================
>> --- branches/bar        (revision 7)
>> +++ branches/bar        (revision 8)
>> 
>> Property changes on: branches/bar
>> ___________________________________________________________________
>> Added: svn:mergeinfo
>> ## -0,0 +0,2 ##
>>     Merged /trunk:r4-5
>>     Merged /branches/foo:r3-7
>> ]]]
>> 
>> The question is why r8 adds mergeinfo for trunk:5 even though it doesn't
>> bring in the changes to fileA.txt made in that revision.
>> 
>> I'm guessing the 2-URL merge added mergeinfo for trunk:4-5 because
>> trunk:4-5 appear in the diff between trunk@HEAD and foo@HEAD.
>> Similarly, the changes to fileA.txt in r5 weren't part of that diff and
>> therefore weren't added to bar.
>> 
>> The resulting state is definitely incorrect.  It can be corrected by
>> an appropriate record-only reverse merge (e.g., «svn merge --record-only
>> -c-5 trunk branches/bar»).
>> 
>> Could Subversion get this right by default?  Good question.  I don't
>> remember whether this has been discussed before.  If anyone else does,
>> do jump in ☺
>> 
>> Cheers,
>> 
>> Daniel
>> 
>>> -----start of 2nd script
>>> ⋮
>>> -----end of 2nd script
>>>
>>> Christophe
>>>
>>> On 5/12/2022 4:41 PM, Christophe Royer wrote:
>>>> Thank you Daniel, below is the script I used (line wrapping might mess
>>>> up a few lines, sorry)
>>>>
>>>> As I was cleaning it up, I realized that in 1.6.17 (yes, still using it,
>>>> and where I saw the issue first) the behavior is different (2-url merge
>>>> gives me a tree conflict).
>>>>
>>>> I am really tempted to delete the extra merginfo-that is my biggest
>>>> concern at this time.
>>>>
>>>> --------- start of script (dos cmd)
>>>> ⋮
>>>> ------------------ end of script
>>>> Christophe
>>>>
>>>> On 5/12/2022 10:52 AM, Daniel Shahaf wrote:
>>>>> Could you post the script, please?  It's hard to answer your question
>>>>> when it describes the details verbally rather than machine-readably.
>>>>>
>>>>> It sounds like a supported scenario.
>>>>>
>>>>> Cheers,
>>>>>
>>>>> Daniel
>>>>>
>>>>>
>>>>> Christophe Royer wrote on Fri, 06 May 2022 21:46 +00:00:
>>>>>> I recently saw some mergeinfo that I can explain but still look wrong to
>>>>>> me. Not sure if it’s a wrong usage of svn, or possibly a defect, and so
>>>>>> far I have not seen any post about this. Here is the scenario (I have a
>>>>>> script, batch file for windows, if needed):
>>>>>>
>>>>>> Seen first using svn 1.6.17, confirmed with with svn 1.14.2
>>>>>>
>>>>>> Here is the setup:
>>>>>>
>>>>>>      * Create repo with trunk and branches
>>>>>>      * Add a file to trunk
>>>>>>      * Create 2 branches from trunk, foo and bar (at this point, neither
>>>>>> branch has mergeinfo for trunk)
>>>>>>      * In foo, edit the existing file
>>>>>>      * Make some changes in trunk (I added a file)
>>>>>>      * Merge trunk to foo (this bring the new file in and adds mergeinfo
>>>>>> for trunk, including the revision where the new file was added)
>>>>>>
>>>>>> Now the fun part:
>>>>>>
>>>>>>      * Do a 2-url merge to merge the changes solely made in foo,
>>>>>> and apply
>>>>>> them to bar
>>>>>>
>>>>>> The diff between trunk and foo shows only one file was edited (the
>>>>>> second file does not show, since merge made it the same in trunk and
>>>>>> foo). But the diff also shows mergeinfo changed between trunk and foo,
>>>>>> so those get merged to bar, which seem appropriate.
>>>>>>
>>>>>> However, it follows that bar now indicates that it has those changes
>>>>>> from trunk (esp. the one revision where the file was added in trunk) but
>>>>>> of course that file is not in bar…And this occurs whether or not I use
>>>>>> –ignore-ancestry.
>>>>>>
>>>>>> I could use cherrypicking instead, but I did not want to have to pick
>>>>>> specific changes (I really want all the changes made in foo, but only
>>>>>> those changes)
>>>>>>
>>>>>> So,
>>>>>>
>>>>>> 1)is that a misuse of svn, an unsupported scenario?. Or is there room
>>>>>> for improvement to the mergeinfo management?
>>>>>>
>>>>>> 2)should I manually delete those “unwanted” mergeinfo? If I don’t, I
>>>>>> have an idea of the issues I can run into. But I am afraid to miss
>>>>>> something here, and removing them would cause other issues.
>>>>>>
>>>>>>
>>>>>> Thanks
>>>>>>
>>>>>> Christophe
  • ... Christophe Royer
    • ... Daniel Shahaf
      • ... Christophe Royer
        • ... Murugan, Gnanaprakash Export License Required - US Collins
        • ... Christophe Royer
          • ... Daniel Shahaf
            • ... Christophe Royer
              • ... Daniel Shahaf

Reply via email to