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 ...] sour...@rev] [TARGET_WCPATH] 2. merge --reintegrate sour...@rev] [TARGET_WCPATH] 3. merge sourc...@n] sourc...@m] [TARGET_WCPATH] 1. The first form is called a "sync" merge, or "cherry-pick" merge: svn merge [-c M[,N...] | -r N:M ...] sour...@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 sou...@rev as it existed at revision N, and sou...@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 (tr...@100), and R marks the "right" side of the merge (tr...@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 (tr...@49) and R marks the right side of the merge (tr...@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 sour...@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 tr...@x and feat...@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 (tr...@x), and R marks the right side of the merge is (feat...@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 sourc...@n] sourc...@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 tr...@500 and feat...@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 (tr...@500), and R marks the right side of the merge is (feat...@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 ^/tr...@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 ^/tr...@500 ^/feat...@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