[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: duplicate merge conflict

From: Stefan Sperling <stsp_at_elego.de>
Date: Wed, 20 Apr 2011 00:50:15 +0200

On Tue, Apr 19, 2011 at 10:56:28AM -0400, Daniel Walter wrote:
> svn merge appears to work with revision numbers but not symbolically
> with tags. Is this expected?
>
> The merge happens twice if I use tags:
> svn merge tag1 tag2 --non-interactive
>
> But when I find the revisions with svn info
> svn info tag1
> Last Changed Rev: 457
>
> svn info tag2
> Last Changed Rev: 467
>
> and then do the merge based on these revision numbers
> svn merge -r 457:467 trunk --non-interactive
>
> the merge happens correctly
>

That is because the tags aren't directly ancestrally related,
while if you are using the branch, the merges source and target
are directly related.

Do not use tags as merge left/right. That's what people used to do in the
CVS world but it doesn't really translate into the Subversion world
with merge tracking. In Subversion you should merge between directly
related branches.

The new svn merge help text in Subversion 1.7 might shed some light on
how svn merge is supposed to be used so I am quoting it below:

=====

merge: Apply the differences between two sources to a working copy path.
usage: 1. merge [-c M[,N...] | -r N:M ...] SOURCE[@REV] [TARGET_WCPATH]
       2. merge --reintegrate SOURCE[@REV] [TARGET_WCPATH]
       3. merge SOURCE1[@N] SOURCE2[@M] [TARGET_WCPATH]

  1. The first form is called a "sync", or "cherry-pick", merge:
     svn merge [-c M[,N...] | -r N:M ...] SOURCE[@REV] [TARGET_WCPATH]

     A sync merge is used to merge into a branch any unmerged changes
     made on its immediate ancestor branch.

     A cherry-picking merge is used to merge specific revisions from
     one branch to another.

     SOURCE is usually a URL. The source of a cherry-picking merge can
     also be a working copy path, in which case the corresponding URL
     of the path is used.

     If REV is specified, it is used as the peg revision for SOURCE,
     i.e. SOURCE is looked up in the repository at revision REV.
     If REV is not specified, the HEAD revision is assumed.

     TARGET_WCPATH is a working copy of the branch the changes will
     be applied to.

     '-r N:M' specifies a revision range to be merged. The difference
     between SOURCE_at_REV as it existed at revision N, and SOURCE_at_REV at
     it existed at revision M, is merged into TARGET_WCPATH. If no
     revision range is specified, the default range of 0:REV is used.
     
     If mergeinfo within TARGET_WCPATH indicates that revisions within
     the range were already merged, changes made in those revisions
     are not merged again. If needed, the range is broken into multiple
     sub-ranges, and each sub-range is merged separately.

     If N is greater than M, the range is a "reverse range".
     A reverse range can be used to undo changes made to SOURCE
     between revisions N and M.

     '-c M' is equivalent to the range '-r <M-1>:M'.
     '-c -M' does the reverse: '-r M:<M-1>'.
     
     Multiple '-c' and/or '-r' options may be specified and mixing of
     forward and reverse ranges is allowed.

       - Sync Merge Example -

     A feature is being developed on a branch called "feature".
     The feature branch is regularly synced with trunk to keep up with
     changes made there.

                 feature +------------------------o-----
                         / ^
                        / /
                       / .............../
         trunk ------+------------L--------------R------
                                r100 r200
     
     In the above diagram, L marks the "left" side of the merge
     (trunk_at_100), and R marks the "right" side of the merge (trunk_at_200).
     The difference between the left and right side is merged into the target.

     To perform the merge, check out a working copy of the feature
     branch and run the following command in the top-level directory
     of the working copy:

         svn merge ^/trunk

     The default revision range is -r0:HEAD, so any unmerged changes
     will be merged.

       - Cherry-picking Merge Example -

     A bug has been fixed on trunk on revision 50. This fix needs to
     be merged from the trunk into the release branch.

            1.x-release +-----------------------o-----
                        / ^
                       / |
                      / |
         trunk ------+--------------------------LR-----
                                                r50
     
     In the above diagram, L marks the left side of the merge (trunk_at_49)
     and R marks the right side of the merge (trunk_at_50).
     The difference between the left and right side is merged into the target.

     To perform the merge, check out a working copy of the release
     branch and run the following command in the top-level directory
     of the working copy:

         svn merge -c50 ^/trunk

     If several commits to trunk were related to the fix, multiple
     revisions can be merged:

         svn merge -c50,54,60 ^/trunk

  2. The second form is called a "reintegrate merge":
     svn merge --reintegrate SOURCE[@REV] [TARGET_WCPATH]

     SOURCE is the URL of a branch to be merged back into (usually) its
     immediate ancestor branch. If REV is specified, it is used a
     the peg revision for SOURCE, i.e. SOURCE is looked up in the
     repository at revision REV. If REV is not specified, the HEAD
     revision is assumed.

     TARGET_WCPATH is a working copy of the branch the changes will
     be applied to.

       - Reintegrate Merge Example -

     A feature has been developed on a branch called "feature".
     The feature branch started as a copy of trunk_at_W. Work on the
     feature has completed and it should be merged back into the trunk.
     
     The feature branch was last synced with its immediate ancestor,
     the trunk, in revision X. So the difference between trunk_at_X and
     feature_at_HEAD contains the complete set of changes that implement
     the feature, and no other changes. These changes are applied to
     the trunk.

                 feature +-------------------------------R
                         / . \
                        / .............. \
                       / . v
         trunk ------+--------------------L------------------o
                    rW rX

     In the diagram above, L marks the left side of the merge (trunk_at_X),
     and R marks the right side of the merge (feature_at_HEAD). The difference
     between the left and right side is merged into the target.

     To perform the merge, check out a working copy of the trunk, and run
     the following command in the top-level directory of the working copy:

         svn merge --reintegrate ^/feature

     To prevent unnecessary merge conflicts, reintegrate merges require
     that TARGET_WCPATH is not a mixed-revision working copy, has no
     local modifications, and has no switched subtrees.

     Reintegrate merges also require that the reintegrate source be fully
     synced with the target since their common branch point.
     In the above example this means that all of the changes made
     on trunk between revision W and revision X are fully merged to
     the feature branch before it can be reintegrated back to trunk.

     After the reintegrate merge, the feature branch cannot be synced
     to the trunk again without merge conflicts. If further work must
     be done on the feature branch, it should be deleted and then re-created.

  3. The third form is called a "2-URL merge":
     svn merge SOURCE1[@N] SOURCE2[@M] [TARGET_WCPATH]

     Two source URLs are specified, together with two revisions N and M.
     The two sources to be compared at the specified revisions, and the
     difference is applied to TARGET_WCPATH, which is a path to a working
     copy of another branch.

     The revisions default to HEAD if omitted.

     If TARGET_WCPATH is omitted, a default value of '.' is assumed,
     unless the sources have identical basenames that match a file
     within '.'; In which case, the differences will be applied to
     that file.

     The sources can also be specified as working copy paths, in which
     case the URLs of the merge sources are derived from the working copies.

     This is the most flexible type of merge, but also the most difficult
     to use. It can be used to merge the differences between two (possibly
     ancestrally unrelated) branches into a working copy of another branch.
     This type of merge should be used very carefully because the probability
     of merge conflicts is quite high. In most use cases, a sync, cherry-pick,
     or reintegrate merge is sufficient and reduces the chances of mistakes.

       - 2-URL Merge Example -

     A feature has been developed on a branch called "feature".
     Development for the upcoming 3.0 release has happened in parallel on
     the "3.x-release" branch. The work on the feature branch must be
     merged to the 3.x-release branch. However, the feature branch and
     the 3.x-release branch are not directly related, so a 2-URL merge
     is needed.
     The feature branch was last synced with its immediate ancestor,
     the trunk, up to revision 500. So the difference between trunk_at_500
     and feature_at_HEAD contains the complete set of changes related to
     the feature, and no other changes. These changes are applied to
     the 3.x-release branch.

                   3.x-release +-----------------------------------o
                               / ^
                              / /
                             / r500 /
         trunk ------+------+-----------------L---------> /
                      \ . /
                       \ ........... /
                        \ . /
                feature +-----------------------------------R

     In the diagram above, L marks the left side of the merge (trunk_at_500),
     and R marks the right side of the merge is (feature_at_HEAD).
     The difference between the left and right side is merged into the target.

     To perform the merge, check out a working copy of the 3.x-release
     branch and run the following command in the top-level directory
     of the working copy:
       
         svn merge ^/trunk_at_500 ^/feature

     Before performing a 2-URL merge, it is a good idea to preview the
     changes which will be merged, because there is no guarantee that
     the merge will be free of conflicts. The preview can be done with
     the svn diff command:

         svn diff ^/trunk_at_500 ^/feature_at_HEAD

     Note that a 2-URL merge can also merge from foreign repositories.
     While SOURCE1 and SOURCE2 must both come from the same repository,
     TARGET_WCPATH may come from a different repository than the sources.
     However, there are some caveats. Most notably, copies made in the
     merge source will be transformed into plain additions in the merge
     target. Also, merge-tracking is not supported.

  The following applies to all types of merges:

  For each merged item a line will be printed with characters reporting
  the action taken. These characters have the following meaning:

    A Added
    D Deleted
    U Updated
    C Conflict
    G Merged
    E Existed
    R Replaced

  Characters in the first column report about the item itself.
  Characters in the second column report about properties of the item.
  A 'C' in the third column indicates a tree conflict, while a 'C' in
  the first and second columns indicate textual conflicts in files
  and in property values, respectively.

  NOTE: Subversion uses the svn:mergeinfo property to track merge
  history. This property is considered at the start of a merge to
  determine what to merge and it is updated at the conclusion of the
  merge to describe the merge that took place. Mergeinfo is used only
  if the two sources are on the same line of history -- if the first
  source is an ancestor of the second, or vice-versa. This is guaranteed
  to be the case when using sync merges and reintegrate merges.
  The --ignore-ancestry option prevents merge tracking and thus
  ignores mergeinfo, neither considering it nor recording it.

Valid options:
  -r [--revision] ARG : ARG (some commands also take ARG1:ARG2 range)
                             A revision argument can be one of:
                                NUMBER revision number
                                '{' DATE '}' revision at start of the date
                                'HEAD' latest in repository
                                'BASE' base rev of item's working copy
                                'COMMITTED' last commit at or before BASE
                                'PREV' revision just before COMMITTED
  -c [--change] ARG : the change made by revision ARG (like -r ARG-1:ARG)
                             If ARG is negative this is like -r ARG:ARG-1
  -N [--non-recursive] : obsolete; try --depth=files or --depth=immediates
  --depth ARG : limit operation by depth ARG ('empty', 'files',
                             'immediates', or 'infinity')
  -q [--quiet] : print nothing, or only summary information
  --force : force operation to run
  --dry-run [--dry] : try operation but make no changes
  --diff3-cmd ARG : use ARG as merge command
  --record-only [--ro] : merge only mergeinfo differences
  -x [--extensions] ARG : Default: '-u'. When Subversion is invoking an
                             external diff program, ARG is simply passed along
                             to the program. But when Subversion is using its
                             default internal diff implementation, or when
                             Subversion is displaying blame annotations, ARG
                             could be any of the following:
                                -u (--unified):
                                   Output 3 lines of unified context.
                                -b (--ignore-space-change):
                                   Ignore changes in the amount of white space.
                                -w (--ignore-all-space):
                                   Ignore all white space.
                                --ignore-eol-style:
                                   Ignore changes in EOL style.
                                -p (--show-c-function):
                                   Show C function name in diff output.
  --ignore-ancestry [--ia] : ignore ancestry when calculating merges
  --accept ARG : specify automatic conflict resolution action
                             ('postpone', 'base', 'mine-conflict',
                             'theirs-conflict', 'mine-full', 'theirs-full',
                             'edit', 'launch')
  --reintegrate [--ri] : merge a branch back into its parent branch
  --allow-mixed-revisions : Allow merge into mixed-revision working copy.
                             Use of this option is not recommended!
                             Please run 'svn update' instead.

Global options:
  --username ARG : specify a username ARG
  --password ARG : specify a password ARG
  --no-auth-cache [--nac] : do not cache authentication tokens
  --non-interactive : do no interactive prompting
  --trust-server-cert : accept unknown SSL server certificates without
                             prompting (but only with '--non-interactive')
  --config-dir [--cd] ARG : read user configuration files from directory ARG
  --config-option ARG : set user configuration option in the format:
                                 FILE:SECTION:OPTION=[VALUE]
                             For example:
                                 servers:global:http-library=serf
Received on 2011-04-20 00:50:54 CEST

This is an archived mail posted to the Subversion Users mailing list.