Some Subversion Merge Scenarios

Since first participating in a development project that uses Subversion, I have enjoyed the ability to delete directories from my project — and have them go away — rename projects, etc. It is easy to create a branch, but my efforts to merge branches into trunk (and vice versa) never seemed to work the first time. I finally determined to write down some scenarios that worked for me. These are written mainly as reminders to me; hopefully they will help you. (Some of the names have been changed to protect the innocent.)

I issued these commands on my Fedora Linux development workstation when I had to do some new (risky) development that would probably destabilize the trunk. Following completion of development, I would want to merge the new code back into the trunk. Here is how I did it:

1. Create a branch with the svn copy command:

$ svn copy https://svn.example.com/repos/examplesuite/trunk \ https://svn.example.com/repos/examplesuite/branches/weldon_odfbug

2. Update from svn to create the branch in working directory:

$ cd ~/work/examplesuite 
$ svn update

3. Later, I wanted to merge any changes that had occurred in the main trunk during the time I was working in my branch — from the trunk to my branch.

First I made sure that the changes I had made to the branch on my computer had been stored to the svn repository's branch, using the svn commit command from my computer, then the svn status command to make sure that the copy of the branch on my computer matched what was on the svn server. Then I issued the following commands.

$ cd ~/work/examplesuite/branches/weldon_odfbug
$ svn merge https://svn.example.com/repos/examplesuite/branches/weldon_odfbug \ https://svn.example.com/repos/examplesuite/trunk .

Note the arguments to the svn merge command: The URL for my branch on the svn server (the destination of the merge) comes first, followed by the URL for the trunk, followed by a dot (for the current directory on my local development machine). The second command above says that I want to "find what has changed in the trunk (2nd argument) relative to the trunk (1st argument), and store the affected files beneath my current directory. (Don't forget the final argument — the dot — for the current directory!) The merge command doesn't change anything on the server. The changes appear beneath the current directory on my local workstation.

4. The svn merge command copies changed files into my working copy of the branch. As it copies the files, it writes their names — one file per line — on my display, (with "M" — for "merge" — in col 1). After I edit the files, make sure they build, test them, (etc.), I commit the merged files to the svn server with the svn commit from the working copy of the branch on my workstation.


Later, when the development on the branch is complete, merge the branch into the trunk:

  1. svn commit all branch changes to the svn server. Run svn update and svn status in both the trunk and branch to make sure that your workstation has the latest versions of both the trunk and branch.
    _
  2. cd to the trunk (on your workstation) — to the directory beneath which you want to merge. (Since all my changes in the branch were in a single directory, I changed to that directory — in the trunk. This example merges only one subdirectory [file2xliff4j/src] from the branch into the trunk.)
$ cd ~/work/examplesuite/trunk/file2xliff4j/src
$ svn merge \
   https://svn.example.com/repos/examplesuite/trunk/file2xliff4j/src \
   https://svn.example.com/repos/examplesuite/branches/weldon_odfbug/file2xliff4j/src \
   .

Note that the arguments to the svn merge command are:

  1. The directory (in the repository trunk) to which we want to merge
  2. The directory (in the repository branch) from which we want to merge (The directories must "match")
  3. The current directory (on my box, represented by a dot) — this must "match" the two above directories (but on my own box, in my own directory structure). Don't forget the final dot!

I think the idea is this: The changes that have been made — and committed by other developers — to the repository branch (the second argument above) are merged with the corresponding files in the repository trunk (the first argument above). The resulting merged candidate files are copied ("checked out"?) to a directory on my workstation (the third argument — a "dot" [period, full stop, …] in my example). I am then expected to verify (visually and by compiling, testing, etc.) that the merged file(s) on my computer are satisfactory. If/when they are, I commit (with the svn commit command) them to (in our example) the repository's trunk — the same way I would commit any changes that I make to the trunk. Then the merge is complete.

Here is what I saw on my display

U    file2xliff4j/ConverterFactory.java
    U    file2xliff4j/OdfExporter.java
    U    file2xliff4j/OdfSkeletonMerger.java
    U    file2xliff4j/MifSkeletonMerger.java
    U    file2xliff4j/SkeletonMerger.java
    U    file2xliff4j/OdfImporter.java
    U    file2xliff4j/OdfHandler.java
    U    file2xliff4j/HtmlSkeletonMerger.java
    U    file2xliff4j/XliffSkeletonMerger.java
    U    file2xliff4j/Format.java

while the merger was happening.

When I typed the svn status, I saw:

?      validatexml.java
    M      file2xliff4j/ConverterFactory.java
    M      file2xliff4j/OdfExporter.java
    M      file2xliff4j/OdfSkeletonMerger.java
    M      file2xliff4j/MifSkeletonMerger.java
    M      file2xliff4j/SkeletonMerger.java
    M      file2xliff4j/OdfImporter.java
    M      file2xliff4j/OdfHandler.java
    M      file2xliff4j/HtmlSkeletonMerger.java
    M      file2xliff4j/XliffSkeletonMerger.java
    M      file2xliff4j/Format.java

(I haven't added — with svn add — validatexml.java yet, I guess.)

3. After verifying that the the merged files (in the trunk, on my workstation) compiled and passed all the tests, I committed them into the trunk (on the subversion server)

4. I resumed development in the trunk. (After a week or two, I deleted my branch from the server.)

— Weldon Whipple