subversion-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stefan Sperling <>
Subject Re: merginfo corruption?
Date Thu, 03 Nov 2016 12:32:19 GMT
On Thu, Nov 03, 2016 at 12:49:26PM +0100, Peter van Hoof wrote:
> I am not even sure how you can commit changes without committing mergeinfo.
> As far as I know that is all automatic.

The designers of SVN's merge-tracking decided to re-use the existing
versioned SVN properties to store mergeinfo, instead of iventing some new
meta-data storage specific to mergeinfo. This decision led to some
downsides for usability which users need to be aware of.

Say a change is merged from trunk and two existing svn:mergeinfo
properties are updated during this merge:

 - on the root of the working copy (the merge target)
 - and a subdirectory A

Further assume that the merge edits the file A/B/C/D/foo.txt.

Now, if the user runs a commit like this:

  svn commit A/B/C/D/foo.txt

Then changes to foo.txt are committed, but the property changes on
the root directory and the subdirectory A remain as local changes
in the working copy. Which is *bad*. The whole working copy should
have been committed.

Say the user uses the TortoiseSVN client and right-clicks on the
file A/B/C/D/foo.txt to commit it. Again, the property changes may
not be committed along unless the user carefully checks the list
of paths in the commit dialog for additional changes which need
to be committed as well.

> I double-checked this and checked out the branch at r8689. This is the result
> % svn co svn://
> % cd backtrace/
> % svn proplist --verbose source/
>    [...snip...]
>    /trunk/source:8667-8688
> So the revision in question is definitely marked as merged there... This
> looks OK, which is also consistent with the fact that subsequent merges from
> trunk showed no problems (r8784, r8788, r8815, r11144).

You're only looking at one path. Mergeinfo is only inherited to paths
which do not have an svn:mergeinfo property themselves.

In my example above, svn:mergeinfo on the root of the working copy
is irrelevant for any child (directory or file) within subtree A.
Only mergeinfo on subtree A is considered for those children (unless
of course where children have svn:mergeinfo themselves).

> I think that the fragmented mergeinfo is a result of cherry-picking commits
> on other branches by other users.

Quite likely. It mostly depends on which merge target people select.

If a subtree A has mergeinfo that means somebody once ran a command like:

  svn merge -c 500 ^/trunk/A ./A

instead of

  svn merge -c 500 ^/trunk .

In TortoiseSVN the merge target is selected by rhight-clicking on it and
selecting the 'Merge' command from the context menu. This should usually
be the working copy root (corresponding to a branch root) but users are
free to click on any other file or directory and often do just that.

> Also, your suggestions do not explain why r8669 wasn't listed in the output
> of the "svn mergeinfo --show-revs eligible ^/trunk ." command. If that
> revision truly was missing from the mergeinfo, it should have been listed
> there.

It seems the mergeinfo command is broken here because it did not consider
subtree mergeinfo on data/stout/zn/zn_19/

Evidently the file 'data/stout/zn/zn_19/' had incomplete mergeinfo
which SVN decided to elide after adding the missing revision:

> > > --- Recording mergeinfo for merge of r2 through r11144 into
> > > 'data/stout/zn/zn_19/':
> > >  U   data/stout/zn/zn_19/
> > > --- Eliding mergeinfo from 'data/stout/zn/zn_19/':
> > >  U   data/stout/zn/zn_19/

Elision only happens when two svn:mergeinfo properties contain the exact
same lines of text, apart from the path-wise difference resulting from the
relative positions of these svn:mergeinfo properties in the directory tree.

So this merge changed mergeinfo on data/stout/zn/zn_19/ in such
a way that it became redundant with mergeinfo on the nearest parent.

> > > --- Recording mergeinfo for merge of r2 through r11144 into 'source':
> > >  U   source
> > > --- Recording mergeinfo for merge of r2 through r11144 into 'tsuite':
> > >  U   tsuite
> > > --- Recording mergeinfo for merge of r2 through r11144 into 'tsuite/auto':
> > >  U   tsuite/auto
> > > --- Recording mergeinfo for merge of r2 through r11144 into
> > > 'tsuite/auto/chianti_all_cool.dat':
> > >  U   tsuite/auto/chianti_all_cool.dat
> > > --- Recording mergeinfo for merge of r2 through r11144 into
> > > 'tsuite/auto/':
> > >  U   tsuite/auto/
> > 
> > Here you should probably perform a commit ("Fixing merginfo of
> > previous merges" or something like that). Note the lines "Eliding
> > mergeinfo from 'data/stout/zn/zn_19/zn_19.coll'" and other "Eliding"
> > lines. This means svn removes subtree mergeinfo there, because it's
> > redundant (it's the same as what the parent directory says).
> OK, this does seem to make a difference and the merge finishes OK, but I do
> not understand why. The "svn merge ^/trunk ." command behaved differently
> before and after the "svn merge --record-only -r1:11144 ^/trunk ." command.

A --record-only merge affects all files and directories with svn:mergeinfo.
Therefore it changed mergeinfo on data/stout/zn/zn_19/

A normal merge only changes svn:mergeinfo properties of files and directories
which were modified by the current merge. The normal merge used to behave like
the --record-only merge but that lead to complaints from users who found the
large amount of property changes after what could be a merge which affected
only a single file rather confusing.

If you had run a merge such as:

  svn merge ^/trunk/data/stout/zn/zn_19/ data/stout/zn/zn_19/

mergeinfo would also have been elided.

More details about mergeinfo can be found in this article:
It's rather old but mostly still relevant.
The section "Mixed Revision Working Copies and Mergeinfo" for example is
now less relevant because merges into mixed-revision working copies have
since been disabled by default.

View raw message