ChatGPT解决这个技术问题 Extra ChatGPT

svn: replace trunk with branch

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?


R
Ray Koren

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.


If you do this, anyone with changes in a working copy in the original trunk will have a conflict, even if their changes should merge. This is because the files are deleted and re-added - they're treated as separate objects with separate history.
@nilbus: Did you try it? IIRC, SVN shows that the files were deleted and readded but internally, it will know that the files have been moved.
Yes. I checked out two copies. In the first copy I moved dir A to A2 and dir B to A. Then moved A to B, then A2 to A. (rename and rename back.) In the 2nd checkout, I made a change to a file and tried to svn update. It conflicted because the file I changed "was deleted". Internally it doesn't save duplicate copies of the files, but the Delete that you see really affects you when it comes to conflicts.
@nilbus: At this point, I'd like to quote Linus Torvalds: "The slogan of Subversion for a while was "CVS done right", or something like that, and if you start with that kind of slogan, there's nowhere you can go. There is no way to do CVS right."
yep. I would agree. To solve this problem, I actually checked out the repo with svn-git, and used git to rebase the branch onto the master.
d
dantiston

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


That may not be the best practice but it is certainly the most efficient when you have a very old trunk and everybody worked on a branch as if it was the trunk. It solved my problem!
I needed to make a label into a new trunk. This is pretty much what I did with the only difference is that the second operation was svn copy {label URL} {trunk URL}.
佚名

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.


Post svn 1.5 you should be able to do merges that preserve history.
C
Chris Nava

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.


A link to Repo would be handy (just for convenience- save a google search :))
Sorry. The spelling made it look like I was referring to a specific tool (edited). Actually, most SVN GUI tools should have a repository browser feature. FYI: I use tortoise tortoisesvn.tigris.org
r
rboerdijk

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


K
Ken Gentle

@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.


Why would "svn move" not be sufficient? Your suggestion seems like squashing a fly with a sledgehammer.
I've been bitten by this 1.4 behavior - if an SVN repository contains moves (renames) of directories or branch/tags, use of svndumpfilter to help reorganize/migrate a repository to a new structure can fail because it doesn't handle the history well. It's documented, I'll dig up the ref. if you like
Could you add the reference to this behaviour?
佚名

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.


Thx for the official info so that I can merge branch to the trunk by the official approch. The keyword is reintegrate
k
kementeus

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


This destroys the trail of history that would be preserved by "svn move".