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