source code patch: http://svn.apache.org/viewvc?view=revision&revision=949307
Background(‘svn merge –record-only’: modify mergeinfo metafile to mark as merged though the diff are not actually merged. Mergeinfo essentially is a meta-data file to record all the merging history. This feature is used to block the automatic change from merging.)
Record-only merging introduces unnecessary, self-referential mergeinfo metafile.
If we want to merge a branch of revision (M+1) into a trunk of revision M, using ‘--record-only merge’, we will have the following lines in mergeinfo file:
The line “Merged /t1:r2-M” is unnecessary and wrong!!! It is self-referential and contains the natural history!!!
If we don’t use ‘--record-only’ option, then self-referential information is successfully filtered out.
How it is diagnosed:
How to reproduce:
Step1) setup the repository
1-1. make a branch ‘t1-branch’ from the trunk ‘t1’
‘svn cp t1 t1-branch’
1-2. commit the change-set
‘svn ci –m “branch t1 to t1-branch”’
Step2) expected result
2-1. merge branch back to the trunk
‘svn merge ^/t1-branch t1’
2-2. print out mergeinfo metadata by ‘svn diff’
Property changes on: t1
=> the trunk is merged from the branch, ‘t1-branch’ of revision 11.
Step3) self-referential mergeinfo from ‘—record-only’ merging.
3-1. record-only merge branch back to the trunk
‘svn merge –record-only ^/t1-branch t1’
3-2. print out mergeinfo metadata by ‘svn diff’
Property changes on: t1
*Result: Beside the information of t1-branch, the trunk, ‘t1’ also has its own history, ‘/t1:r2-10’. It’s unnecessary self-referential information.
When running ‘svn merge –record-only’, they are creating self-referential mergeinfo because it fails to filter out the self-referential information.
In the buggy case, it contains self-referential mergeinfo because of appending every mergeinfo.
To avoid self-referential mergeinfo, we need to register this mergeinfo to the ‘implicit mergeinfo’ data structure so that ‘filter_natrual_history_from_mergeinfo()’ function can get rid of it.
To avoid self-referential mergeinfo, we need to get a ‘implicit mergeinfo’ of self-referential data. With this data, ‘filter_natural_history_from_mergeinfo()’ function can get rid of the self-referential info. In ‘populate_remaining_ranges’ function, there’s a routine that gets the target’s implicit mergeinfo during ‘–record-only merges’.
In the first call of ‘populate_remaining_ranges’ with ‘--record-only’ option, the mergeinfo is always the self-referential info while the arguments ‘url1’ and ‘url2’ are the same.
#0 populate_remaining_ranges (
#1 do_directory_merge (...) at subversion/libsvn_client/merge.c:7826
#2 do_merge (..., record_only=1,) at subversion/libsvn_client/merge.c:8312
#3 merge_peg_locked (...) at subversion/libsvn_client/merge.c:10100
#4 merge_peg_cb (...) at subversion/libsvn_client/merge.c:10134
#5 svn_wc__call_with_write_lock (...) at subversion/libsvn_wc/lock.c:1724
#6 svn_client_merge_peg3 (...) at subversion/libsvn_client/merge.c:10179
#7 svn_cl__merge (...) at subversion/svn/merge-cmd.c:322
#8 main (argc=5, argv=0x7fffffffe7b8) at subversion/svn/main.c:2296
After calculating the revision range of the merge info, it returns to ‘do_directory_merge’ function. In ‘do_directory_merge’ function, ‘filter_natural_history_from_mergeinfo’ function called by ‘record_mergeinfo_for_dir_merge’.
static svn_error_t *
/* If we are honoring mergeinfo, then for each item in
NOTIFY_B->CHILDREN_WITH_MERGEINFO, we need to calculate what needs to be
merged, and then merge it. Otherwise, we just merge what we were asked
to merge across the whole tree. */
/* Record mergeinfo where appropriate.*/
static svn_error_t *
/* Record mergeinfo on any subtree affected by the merge or for
every subtree if this is a --record-only merge. Always record
mergeinfo on the merge target CHILDREN_WITH_MERGEINFO. */
for (i = 0; i < notify_b->children_with_mergeinfo->nelts; i++)
else /* Record mergeinfo on CHILD. */
/* Filter any ranges from each child's natural history before
setting mergeinfo describing the merge. */
child->implicit_mergeinfo, &range, iterpool));
/* If the mergeinfo has only natural history like self-referential info, then the corresponding revision range is deleted and returns in the following statement. However, the buggy version has no implicit information denoting self-reference, so that it does not return but print out the self-referential info */
if (child_merge_rangelist->nelts == 0)
} /* (i = 0; i < notify_b->children_with_mergeinfo->nelts; i++) */
The patch is :
--- subversion/trunk/subversion/libsvn_client/merge.c 2010/05/28 21:40:36 949306
+++ subversion/trunk/subversion/libsvn_client/merge.c 2010/05/28 21:44:18 949307
@@ -4112,6 +4112,9 @@ populate_remaining_ranges(apr_array_head
svn_revnum_t gap_start, gap_end;
+ svn_boolean_t child_inherits_implicit;
+ svn_client__merge_path_t *parent;
+ int parent_index;
iterpool = svn_pool_create(pool);
@@ -4125,6 +4128,46 @@ populate_remaining_ranges(apr_array_head
svn_client__merge_path_t *child =
+ parent = NULL;
+ /* Issue #3646 'record-only merges create self-referential
+ mergeinfo'. Get the merge target's implicit mergeinfo (natural
+ history). We'll use it later to avoid setting self-referential
+ mergeinfo -- see filter_natural_history_from_mergeinfo(). */
+ if (i == 0) /* First item is always the merge target. */
/* by calling get_full_mergeinfo, we can make a implicit mergeinfo and this information is used later to filter out by filter_natural_history_from_mergeinfo. In no ‘record-only’ case, ‘get_full_mergeinfo’ function is also called so that implicit information is generated. Consequently, it doesn’t have self-referential info */
+ SVN_ERR(get_full_mergeinfo(NULL, /* child->pre_merge_mergeinfo */
+ NULL, /* child->indirect_mergeinfo */
+ svn_mergeinfo_inherited, ra_session,
+ MAX(revision1, revision2),
+ MIN(revision1, revision2),
+ merge_b->ctx, pool, iterpool));
Is there any log message?
Can ErrLog insert a log message?