157
votes

What is the best way to make one of the branches of a subversion repository the new trunk?

There has been a major rewrite for the entire system: things have been moved around, rewritten, replaces, removed, renamed etc. The rewritten code has been tested and is ready to replace the old trunk.

Basically, the the old mainline (Trunk 5) is tagged and will end here. The rewritten branch (Branch 6) is to become the new mainline (Trunk 7):

Trunk(1) --> Trunk(2) --> Trunk(5) --> ×          +--> new Trunk(7)
  \                             \                 |
  fork                         merge             ???
    \                             \               |
     +--> Branch(3) --> Branch(4) --> Branch(6) --+

All ongoing changes from the old 'Trunk' are already incorporated in the 'Rewritten branch'

How can I do this?

8

8 Answers

119
votes

Use svn move to move the contents of the old trunk somewhere else and rename the branch to trunk afterward.

Note that copy and move in svn work like file operations. You can use them to move/copy stuff around in your repository and these changes are versioned as well. Think of "move" as "copy+delete".

[EDIT] Nilbus just notified me that you will get merge conflicts when you use svn move.

I still think that this is the correct approach. It will cause conflicts but if you merge carefully, chances are that you won't lose any data. If that bothers you, use a better VCS like Mercurial or Git.

67
votes

I agree with using the svn move command to accomplish this goal.

I know others here think its unusual, but I like to do it this way. When I have a feature branch and am ready to merge it with a trunk that has also be significantly modified, I will merge it to a new branch, usually named <FeatureBranchName>-Merged. Then I resolve conflicts and test the merged code. Once that's complete I move the trunk to the tags folder so I don't lose anything. Lastly I move my <FeatureBranchName>-Merged to the trunk.

In addition I prefer to avoid the working copy when doing the moves, here are samples of the commands:

svn move https://SVNUrl/svn/Repo/trunk https://SVNUrl/svn/Repo/tags/AnyName

svn move https://SVNUrl/svn/Repo/branches/BranchName-Merged https://SVNUrl/svn/Repo/trunk

Note: I use 1.5

12
votes

I was just looking at this problem recently, and the solution that I was very happy with was performing

svn merge --ignore-ancestry trunk-url branch-url

on the working copy of my trunk.

This does not try to apply changes in a historical manner (maintaining changes in the trunk). It simply "applies the diff" between the trunk and the branch. This will not create any conflicts for your users in the files that were not modified. You will however lose your Historical information from the branch, but that happens when you peform a merge anyway.

9
votes

Recommend you do these changes via the repository browser tool.

Attempting large delete+move operations via the working copy is a great way to kill the working copy. If you are forced to use the working copy, perform incremental commits after each delete or move operation and UPDATE your working copy after each commit.

4
votes

If you want to make the branch the new trunk (i.e.) get rid of all changes in the trunk which were made since the branch was created, you could 1. Create a branch of the trunk (for backup purposes) 2. "revert changes" on the trunk (select all revisions after the branch was created 3. Merge branch back to trunk.

History should be remaining this way.

Regards, Roger

3
votes

@Aaron Digulla and @kementeus solutions are workable. For Subversion 1.4 repositories, copy/move operations can make future migration to a different repository structure or splitting repositories difficult.

I believe 1.5's improvements include better resolution of move/copy history, so it probably wouldn't be an issue for a 1.5 repository.

For a 1.4 repository, I'd recommend using svnadmin dump and svndumpfilter to perform the movement of the existing trunk elsewhere, then moving the branch to the trunk with the same mechanism. Load the two dumpfiles into a test repository, verify, then move it to production.

Of course, backup your existing repository before starting.

This preserves history without recording the move/copy explicitly and makes future re-organization, preserving history, easier.


Edit: As requested, the documentation of the 1.4 behavior, from the 1.4 Red-Bean book, Filtering Repository History

Also, copied paths can give you some trouble. Subversion supports copy operations in the repository, where a new path is created by copying some already existing path. It is possible that at some point in the lifetime of your repository, you might have copied a file or directory from some location that svndumpfilter is excluding, to a location that it is including. In order to make the dump data self-sufficient, svndumpfilter needs to still show the addition of the new path—including the contents of any files created by the copy—and not represent that addition as a copy from a source that won't exist in your filtered dump data stream. But because the Subversion repository dump format only shows what was changed in each revision, the contents of the copy source might not be readily available. If you suspect that you have any copies of this sort in your repository, you might want to rethink your set of included/excluded paths, perhaps including the paths that served as sources of your troublesome copy operations, too.

This applies to migrations/reorganizations using svndumpfilter. There are times when a little extra work now can save a lot of extra work later, and by keeping an easy use of svndumpfilter available for future migrations/reorganizations mitigates the risk at a relatively low cost.

2
votes

While the answers above will work, they aren't best practice. The latest svn server and client track merges for you. So svn knows which revisions you've merged into a branch and from where. This helps a lot when keeping a branch up-to-date and then merging it back into the trunk.

No matter which version of Subversion you're using however, there is a best practice method for getting changes in a branch back into trunk. It is outlined in the Subversion manual: Version Control with Subversion, Chapter 4. Branching and Merging, Keeping a Branch in Sync.

-3
votes

It is a really weird/unusual configuration in SVN, even I think it is far from being a "good practice" at all, anyway, I guess you could do something like:

  • Checkout all the sourcetree (svn co therootsourcetree)
  • Remove the trunk (svn rm trunk)
  • Copy the branch to the trunk (svn cp branches/thebranch /trunk)
  • Remove the branch (svn rm branches/thebranch)
  • Commit the changes

Good luck