You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Stefan Sperling <st...@elego.de> on 2010/10/29 15:57:00 UTC

RFC: revised text for "svn help merge"

Our current help texts explain syntax of commands quite well,
but they don't really explain the semantics. This makes svn help
fairly useless for people who just want to get going with their
first steps in Subversion.

The Subversion book on the other hand explains the semantics very well,
but it literally takes pages upon pages for doing so. It is quite
detailed and often provides too much information (and verbiage) for
people who just want to get going. Many people end up coming to the #svn
IRC channel looking for help, only to be told to read the book anyway.

I think "svn help" should cover more middle ground. To illustrate what
I'd like to do, I've rewritten the help text for "svn merge", because
its current form is a particularly bad example of virtually useless help
text for people who just want to get started.

In Subversion courses and workshops I give during my work at elego,
I usually introduce the merge functionality of Subversion based on
use cases people will need to deal with. I've found that people have
little difficulty working with "svn merge" after being given a short
use-case focused introduction.

So the proposed help text below centers around the most common use cases.
It is longer than the old help text, but leaves out many details covered
in the book. Note that I've also changed the order in which the various
merge types are presented. The current help text starts out explaining
the syntax of 2-URL merges, which are rarely needed these days, and the
most difficult to understand at the semantic level.

I'd like to revise help texts for other subcommands in a similar manner.
Eventually, I'd like svn help will point out in which order the subcommand
help texts can be read to receive a small introductory tutorial on svn.
But it would also refer people to the book for more information.

Of course, good texts present just the right amount of information
with as little words as possible. I don't think the below text is as
good as it can get yet, but I got tired of tweaking it for today.

Thoughts? Comments?

Thanks,
Stefan


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" merge, 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 into a branch selected
     changes made on another branch.

     In both cases, SOURCE is a URL. 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.

     The source can also be specified as working copy path, in which case
     the URL of the merge source is derived from the working copy.

     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@REV as it existed at revision N, and SOURCE@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". Such a 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@100),
     and R marks the "right" side of the merge (trunk@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. To merge only a specific range of revisions, specify a
     revision range:
       
         svn merge -r100:200 ^/trunk
     

       - Cherry-picking Merge Example -

     A bug has been fixed on trunk on revision 50. This fix needs to
     be released in the next release of the line of 1.x releases.
     The 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@49)
     and R marks the right side of the merge (trunk@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 feature 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
     to 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 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.

     The source can also be specified as working copy path, in which case
     the URL of the merge source is derived from the working copy.


       - Reintegrate Merge Example -

     A feature has been developed on a branch called "feature".
     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@X and
     feature@HEAD contains the complete set of changes related to the feature,
     and no other changes. This diff is applied to the trunk.

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

     In the diagram above, L marks the left side of the merge (trunk@X),
     and R marks the right side of the merge is (feature@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, the reintegrate merge requires
     that TARGET_WCPATH is not a mixed-revision working copy, and has no
     local modifications, and has no switched subtrees.  It also requires
     that all changes which were merged into the reintegrate source have
     also been merged into the target.

     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. If possible, avoid doing 2-URL merges.


       - 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. There is huge demand for having the feature
     in the upcoming 3.0 release, so it has been decided to merge it into 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, in revision 500. So the difference between trunk@500 and
     feature@HEAD contains the complete set of changes related to the feature,
     and no other changes. This diff is applied to the 3.x-release branch.

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

     In the diagram above, L marks the left side of the merge (trunk@500),
     and R marks the right side of the merge is (feature@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@500 ^/feature

     Before performing a 2-UL merge, it is a good idea to preview the changes
     which will be merged. This can be done with the svn diff command:

         svn diff ^/trunk@500 ^/feature@HEAD


  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 will only record metadata to track the merge (mergeinfo)
  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 overrides this, forcing Subversion to regard
  the sources as unrelated and not to track the merge.

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

Re: RFC: revised text for "svn help merge"

Posted by Stephen Butler <sb...@elego.de>.
On Oct 29, 2010, at 18:13 , Stefan Sperling wrote:

> On Fri, Oct 29, 2010 at 12:01:41PM -0400, C. Michael Pilato wrote:
>> On 10/29/2010 11:57 AM, Stefan Sperling wrote:
>>> Thoughts? Comments?
>> 
>> I've not reviewed your suggested help text.  But merely seeing the size of
>> makes me wonder ... is it time for 'svn help SUBCOMMAND --verbose' ?
> 
> Sure, no problem.

Just for fun, here are the line counts of Stefan's new help text, svn trunk and 
the merge commands of a few other VC tools.

Steve

$ wc -l new-merge-help.txt 
     302 new-merge-help.txt
$ svn help merge | wc -l
      91
$ git help merge | wc -l
     447
$ hg help merge | wc -l
      26
$ bzr help merge | wc -l
     106



--
Stephen Butler | Senior Consultant
elego Software Solutions GmbH
Gustav-Meyer-Allee 25 | 13355 Berlin | Germany
fon: +49 30 2345 8696 | mobile: +49 163 25 45 015
fax: +49 30 2345 8695 | http://www.elegosoft.com
Geschäftsführer: Olaf Wagner | Sitz der Gesellschaft: Berlin
Amtsgericht Charlottenburg HRB 77719 | USt-IdNr: DE163214194


Re: RFC: revised text for "svn help merge"

Posted by Stefan Sperling <st...@elego.de>.
On Fri, Oct 29, 2010 at 12:01:41PM -0400, C. Michael Pilato wrote:
> On 10/29/2010 11:57 AM, Stefan Sperling wrote:
> > Thoughts? Comments?
> 
> I've not reviewed your suggested help text.  But merely seeing the size of
> makes me wonder ... is it time for 'svn help SUBCOMMAND --verbose' ?

Sure, no problem.

Re: RFC: revised text for "svn help merge"

Posted by Stefan Sperling <st...@elego.de>.
On Sat, Oct 30, 2010 at 03:18:21PM -0500, Peter Samuelson wrote:
> 
> [Hyrum K. Wright]
> > Would it be possible to define a simple markup format, and then just
> > put these strings in a text file and process that, similar to what we
> > do with our sql statements now.  Is there a markup format which
> > already exists which would suit this purpose?
> 
> I have to say I kinda like the git approach.  'git merge --help'
> literally spawns 'man git-merge', which is a full-featured manpage,
> including a references section and all that.  For a tool that has no
> ambitions to work on anything but a Unix platform, it seems like a
> pretty good approach.  I suppose it would be problematic for typical
> Windows installs of the command line binaries.
> 
> Maintaining real man pages is an idea I've toyed with in my brain for
> quite some time. 

I'll focus on content for now, and not on what file format or markup
the help texts should live in. It's a separate issue so it can be dealt
with separately. And I think the content is way more important than
the format.

That said, I think the embedded strings are fine. They always work on
any platform and aren't hard to maintain.

> I don't understand why it would be a bad thing to replace the book, at
> least for usage, semantic information, and examples.

There is no reason to replace the book. The book is a great resource,
and will always provide a more thorough and complete picture.

Stefan

Re: RFC: revised text for "svn help merge"

Posted by Peter Samuelson <pe...@p12n.org>.
[Hyrum K. Wright]
> Would it be possible to define a simple markup format, and then just
> put these strings in a text file and process that, similar to what we
> do with our sql statements now.  Is there a markup format which
> already exists which would suit this purpose?

I have to say I kinda like the git approach.  'git merge --help'
literally spawns 'man git-merge', which is a full-featured manpage,
including a references section and all that.  For a tool that has no
ambitions to work on anything but a Unix platform, it seems like a
pretty good approach.  I suppose it would be problematic for typical
Windows installs of the command line binaries.

Maintaining real man pages is an idea I've toyed with in my brain for
quite some time.  It should even be possible to dump them to plain
text, at release roll time, for the benefit of platforms that are
nroff-deprived.  These would end up in a Subversion 'library' directory
alongside the binaries, shared libraries, message catalogs and whatnot,
and the command-line binaries would launch 'more' or 'notepad' or
something, to show a file.  Automatically selecting the correct
localized file is, unfortunately, something 'man' already does pretty
well, that one would have to reinvent for man-less platforms.

(I do have to say I have a bias against docbook, like most other uses
of XML, as it's quite verbose and clunky for text editing.  nroff
format may seem quaint, but it's actually quite editable once you get
used to it.)

I don't know how localization of manpages usually work, but a lot of
projects ship piles of translated manpages.  I assume the pages in each
language are just separately maintained, with translators taking cues
from the updates to the original version.


> On Sat, Oct 30, 2010 at 8:28 AM, Stefan Sperling <st...@elego.de> wrote:
> > I'd like to keep the texts short enough so they can still be
> > embedded as C strings into the binary. Being constrained is a good
> > thing because I don't want the help texts to end up replacing the
> > book.

I don't understand why it would be a bad thing to replace the book, at
least for usage, semantic information, and examples.  The book, or
something like it, is clearly still needed to communicate concepts and
best practices.

Peter

Re: RFC: revised text for "svn help merge"

Posted by "Hyrum K. Wright" <hy...@mail.utexas.edu>.
On Sat, Oct 30, 2010 at 8:28 AM, Stefan Sperling <st...@elego.de> wrote:
> On Fri, Oct 29, 2010 at 06:56:24PM +0200, Daniel Shahaf wrote:
>> C. Michael Pilato wrote on Fri, Oct 29, 2010 at 12:01:41 -0400:
>> > On 10/29/2010 11:57 AM, Stefan Sperling wrote:
>> > > Thoughts? Comments?
>> >
>> > I've not reviewed your suggested help text.  But merely seeing the size of
>> > makes me wonder ... is it time for 'svn help SUBCOMMAND --verbose' ?
>>
>> Don't you think the help text you've written has outgrown being
>> maintained as a string literal in some C source file?
>
> I've already been toying with the idea of moving the help texts into
> their own file (e.g. help.c).  The C strings defined in that file would
> then be used by main.c.
>
> The file could possibly be auto-generated, but we'd have to be careful
> not to make things harder for translators if we did that.

Would it be possible to define a simple markup format, and then just
put these strings in a text file and process that, similar to what we
do with our sql statements now.  Is there a markup format which
already exists which would suit this purpose?

>> We could maintain it in *.txt/manpage/docbook format.  If you'd like it
>> to be shipped alongside our libraries/binaries, I'm sure that can be
>> arranged...
>
> I'd like to keep the texts short enough so they can still be embedded
> as C strings into the binary. Being constrained is a good thing because
> I don't want the help texts to end up replacing the book.
>

Re: RFC: revised text for "svn help merge"

Posted by Stefan Sperling <st...@elego.de>.
On Fri, Oct 29, 2010 at 06:56:24PM +0200, Daniel Shahaf wrote:
> C. Michael Pilato wrote on Fri, Oct 29, 2010 at 12:01:41 -0400:
> > On 10/29/2010 11:57 AM, Stefan Sperling wrote:
> > > Thoughts? Comments?
> > 
> > I've not reviewed your suggested help text.  But merely seeing the size of
> > makes me wonder ... is it time for 'svn help SUBCOMMAND --verbose' ?
> 
> Don't you think the help text you've written has outgrown being
> maintained as a string literal in some C source file?

I've already been toying with the idea of moving the help texts into
their own file (e.g. help.c).  The C strings defined in that file would
then be used by main.c.

The file could possibly be auto-generated, but we'd have to be careful
not to make things harder for translators if we did that.

> We could maintain it in *.txt/manpage/docbook format.  If you'd like it
> to be shipped alongside our libraries/binaries, I'm sure that can be
> arranged...

I'd like to keep the texts short enough so they can still be embedded
as C strings into the binary. Being constrained is a good thing because
I don't want the help texts to end up replacing the book.

Re: RFC: revised text for "svn help merge"

Posted by Daniel Shahaf <d....@daniel.shahaf.name>.
C. Michael Pilato wrote on Fri, Oct 29, 2010 at 12:01:41 -0400:
> On 10/29/2010 11:57 AM, Stefan Sperling wrote:
> > Thoughts? Comments?
> 
> I've not reviewed your suggested help text.  But merely seeing the size of
> makes me wonder ... is it time for 'svn help SUBCOMMAND --verbose' ?

Don't you think the help text you've written has outgrown being
maintained as a string literal in some C source file?

We could maintain it in *.txt/manpage/docbook format.  If you'd like it
to be shipped alongside our libraries/binaries, I'm sure that can be
arranged...

Re: RFC: revised text for "svn help merge"

Posted by "C. Michael Pilato" <cm...@collab.net>.
On 10/29/2010 11:57 AM, Stefan Sperling wrote:
> Thoughts? Comments?

I've not reviewed your suggested help text.  But merely seeing the size of
makes me wonder ... is it time for 'svn help SUBCOMMAND --verbose' ?

I, for one, would love to offer two levels of built-in help.  And if the
second level was good enough, I could drop the Reference chapter out of the
book altogether.  :-)

-- 
C. Michael Pilato <cm...@collab.net>
CollabNet   <>   www.collab.net   <>   Distributed Development On Demand


Re: revised text for "svn help merge"

Posted by Stefan Sperling <st...@elego.de>.
On Fri, Oct 29, 2010 at 01:52:42PM -0400, Bob Archer wrote:
> > So the proposed help text below centers around the most common use
> > cases.
> 
> Wow... this looks great. It will be nice to have this at the command line. 

Glad to hear that. Would you be willing to help out with this task?
No strong commitment required -- just if you feel like making improvements
to the various texts and send patches, that would be valuable help.

Based on cmpilato's suggestion, I'd like each subcommand to have a
short help text and a long one. The short text would be a subset of
the long text, so the code can decide to show the extra text if --verbose
was passed.

Then I'd like svn help to print:

  For a short introductory tutorial to Subversion, run 'svn help -v'.

The verbose help text for svn help would briefly explain the basics of
Subversion's repository design (versioned tree, revision numbers,
basic operations possible on the versioned tree), and the basic
checkout/update/edit/commit work cycle with a working copy.

It would then refer to the next subcommand -v help text:
  To continue the tutorial, run 'svn help -v checkout'

So the verbose help texts would be linked in some sensible order,
but would also stand on their own, much like chapters in a book.

> I read through it all... only found one small nit:
> 
> >      If several commits to trunk were related to the fix, multiple
> > revisions
> >      to can be merged:
> > 
> >          svn merge -c50,54,60 ^/trunk
> 
> Should that perhaps read:
> 
> If several commits to trunk were related to the fix, multiple revisions too can be merged:
> 
> too meaning also? Perhaps it would read better as:
> 
> If several commits to trunk were related to the fix, multiple revisions can be merged:
> 
> or even:
> 
> If several commits to trunk were related to the fix, multiple revisions can be supplied:
> 
> ????

Yes, thanks, that was a typo.

I meant to say "multiple revisions can be merged". But I like your second
variant, too.

Thanks,
Stefan

RE: revised text for "svn help merge"

Posted by Bob Archer <Bo...@amsi.com>.
> So the proposed help text below centers around the most common use
> cases.

Wow... this looks great. It will be nice to have this at the command line. 

I read through it all... only found one small nit:

>      If several commits to trunk were related to the fix, multiple
> revisions
>      to can be merged:
> 
>          svn merge -c50,54,60 ^/trunk

Should that perhaps read:

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

too meaning also? Perhaps it would read better as:

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

or even:

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

????

BOb

Re: RFC: revised text for "svn help merge"

Posted by Stefan Sperling <st...@elego.de>.
On Mon, Nov 01, 2010 at 12:15:32PM -0400, Paul Burba wrote:
> Hi Stefan,
> 
> Disregarding the other questions on this thread re how to store the
> help text and whether to introduce a two-tier --verbose help option
> (which seems reasonable), I like the basic concept.
> Comments/suggestions are inline:

Thanks a bunch! I agree with all your suggestions and will, well,
merge them into the next revision of this help text when I find
some spare time :)

Stefan

Re: RFC: revised text for "svn help merge"

Posted by Paul Burba <pt...@gmail.com>.
On Fri, Oct 29, 2010 at 11:57 AM, Stefan Sperling <st...@elego.de> wrote:
> Our current help texts explain syntax of commands quite well,
> but they don't really explain the semantics. This makes svn help
> fairly useless for people who just want to get going with their
> first steps in Subversion.
>
> The Subversion book on the other hand explains the semantics very well,
> but it literally takes pages upon pages for doing so. It is quite
> detailed and often provides too much information (and verbiage) for
> people who just want to get going. Many people end up coming to the #svn
> IRC channel looking for help, only to be told to read the book anyway.
>
> I think "svn help" should cover more middle ground. To illustrate what
> I'd like to do, I've rewritten the help text for "svn merge", because
> its current form is a particularly bad example of virtually useless help
> text for people who just want to get started.
>
> In Subversion courses and workshops I give during my work at elego,
> I usually introduce the merge functionality of Subversion based on
> use cases people will need to deal with. I've found that people have
> little difficulty working with "svn merge" after being given a short
> use-case focused introduction.
>
> So the proposed help text below centers around the most common use cases.
> It is longer than the old help text, but leaves out many details covered
> in the book. Note that I've also changed the order in which the various
> merge types are presented. The current help text starts out explaining
> the syntax of 2-URL merges, which are rarely needed these days, and the
> most difficult to understand at the semantic level.
>
> I'd like to revise help texts for other subcommands in a similar manner.
> Eventually, I'd like svn help will point out in which order the subcommand
> help texts can be read to receive a small introductory tutorial on svn.
> But it would also refer people to the book for more information.
>
> Of course, good texts present just the right amount of information
> with as little words as possible. I don't think the below text is as
> good as it can get yet, but I got tired of tweaking it for today.
>
> Thoughts? Comments?
>
> Thanks,
> Stefan

Hi Stefan,

Disregarding the other questions on this thread re how to store the
help text and whether to introduce a two-tier --verbose help option
(which seems reasonable), I like the basic concept.
Comments/suggestions are inline:

> 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]

Minor nit, but 2 and 3 should align with 1.

>  1. The first form is called a "sync" merge, 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 into a branch selected
>     changes made on another branch.

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

>     In both cases, SOURCE is a URL. 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.

I'd remove the line "In both cases, SOURCE is a URL." because it's a
bit unclear.  Are we saying "*IF* source is a URL, then *something*"
or "SOURCE *must* be a URL", or something else?

>     The source can also be specified as working copy path, in which case
>     the URL of the merge source is derived from the working copy.

This is not entirely true since a sync merge requires a URL as the source:

  >svn merge trunk branch
  ..\..\..\subversion\svn\merge-cmd.c:222: (apr_err=195002)
  svn: A working copy merge source needs an explicit revision

This comment from merge-cmd.c sums up why not:

  /* Catch 'svn merge wc_path1 wc_path2 [target]' without explicit
     revisions--since it ignores local modifications it may not do what
     the user expects.  Forcing the user to specify a repository
     revision should avoid any confusion. */

So we should probably go with something like this:

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

>     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@REV as it existed at revision N, and SOURCE@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". Such a 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
                                                        ^
That comma seems unnecessary (and yes, I probably put it there :-)

>     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@100),
>     and R marks the "right" side of the merge (trunk@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. To merge only a specific range of revisions, specify a
>     revision range:
>
>         svn merge -r100:200 ^/trunk

I'd remove the preceding section starting at "To merge only a specific
range", because in my book "svn merge -r100:200 ^/trunk" *is* a cherry
pick (i.e. cherry picking doesn't imply one cherry, it might be 200
cherries!).

>       - Cherry-picking Merge Example -
>
>     A bug has been fixed on trunk on revision 50. This fix needs to
>     be released in the next release of the line of 1.x releases.
>     The fix needs to be merged from the trunk into the release branch.

The line "This fix needs to be released in the next release of the
line of 1.x releases." seems superfluous, I think just this conveys
what we need here:

     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@49)
>     and R marks the right side of the merge (trunk@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 feature 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
>     to 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 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.
>
>     The source can also be specified as working copy path, in which case
>     the URL of the merge source is derived from the working copy.

Actually the reintegrate source can't be a WC path; you'll get the
same 'svn: A working copy merge source needs an explicit revision' I
mentioned above.  But unlike the previous case you can't get by this
by specifying a revision range, since --reintegrate doesn't support
that:

  >svn merge feature trunk --reintegrate -r0:HEAD
  ..\..\..\subversion\svn\main.c:2357: (apr_err=205000)
  svn: Try 'svn help' for more info
  ..\..\..\subversion\svn\merge-cmd.c:64: (apr_err=205000)
  svn: -r and -c can't be used with --reintegrate

>       - Reintegrate Merge Example -
>
>     A feature has been developed on a branch called "feature".

If we add some language like this, "The feature branch started as a
copy of trunk@W", it will make explaining one of the reintegrate
requirements below a lot easier.

>     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@X and
>     feature@HEAD contains the complete set of changes related to the feature,

I know it is somewhat redundant, but I would say "the feature branch"
rather than "the feature" above.

>     and no other changes. This diff is applied to the trunk.
>
>                 feature  +-------------------------------R
>                         /                               . \
>                        /                  ..............   \
>                       /                  .                  v
>         trunk ------+--------------------L------------------o
>                     rW                  rX
                      ^^
                   Add this



>     In the diagram above, L marks the left side of the merge (trunk@X),
>     and R marks the right side of the merge is (feature@HEAD).
                                              ^^
                                           Remove "is"

>     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, the reintegrate merge requires
>     that TARGET_WCPATH is not a mixed-revision working copy, and has no
>     local modifications, and has no switched subtrees.

A bit cleaner?

     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.

>                                                          It also requires
>     that all changes which were merged into the reintegrate source have
>     also been merged into the target.

This last requirement is tough to explain both briefly and in a way
that will be properly understood by the majority of users.  How does
this sound?

     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.

Do we want to raise the other option of using a record-only merge to
work around this limitation?  Or do we save that for --really-verbose
;-P ?

>  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.  If possible, avoid doing 2-URL merges.

Maybe replace this "If possible, avoid doing 2-URL merges" with "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. There is huge demand for having the feature
>     in the upcoming 3.0 release, so it has been decided to merge it into the
>     3.x-release branch.

"There is huge demand for having the feature in the upcoming 3.0
release, so it has been decided to merge it into 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, in revision 500.

Are you saying the sync *done* in r500 or was the sync *up to* r500
from trunk, but done in some subsequent revision?  I assume you mean
the latter, in which case you'll need to tweak your diagram:

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

> So the difference between trunk@500 and
>     feature@HEAD contains the complete set of changes related to the feature,
>     and no other changes. This diff is applied to the 3.x-release branch.
>
>                   3.x-release  +-----------------------------------o
>                               /                                    ^
>                              /                                    /
>                             /                                    /
>         trunk ------+------+------------------L-----            /
>                      \                         .               /
>                       \                         ...........   /
>                        \                                   . /
>                feature  +---------------------o-------------R
>                                             r500
>
>     In the diagram above, L marks the left side of the merge (trunk@500),
>     and R marks the right side of the merge is (feature@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@500 ^/feature
>
>     Before performing a 2-UL merge, it is a good idea to preview the changes
>     which will be merged. This can be done with the svn diff command:
>
>         svn diff ^/trunk@500 ^/feature@HEAD

Do we want to say that the above example in no-way guarantees a clean merge?

>  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 will only record metadata to track the merge (mergeinfo)
>  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 overrides this, forcing Subversion to regard
>  the sources as unrelated and not to track the merge.

Reworked this a bit to convey the idea that mergeinfo is used two
important ways: To consider what to merge and then to describe what
just got merged.

  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.

Paul