How do I convert unstructured SVN folders to trunk/branches style and retain history?
I have a SVN repository which is currently structured like so:
/versions
/1.0.0
/1.0.1
/1.0.2
/1.1.0
/(etc)
What happened here is that when it was time to start a new release, a team member would make a copy of the previous version's folder and rename that folder; then add/commit that new folder into SVN.
As a consequence, all of the revision history for a given version-folder is limited just to changes made in that version-folder. SVN thinks that each file in each version-folder was created anew at the time of version-folder creation.
So what I'd like to do is convert this series of folders into a tradi开发者_Go百科tional trunk/branches/tag SVN structure.
Is it possible to somehow "reconcile" the revision histories of each of these versioned folders back into one common revision-history tree?
Just to clarify: When you say they would add/commit, you mean they didn't do an svn copy of the old version to the new version name, correct? Based on assuming I understood that correctly...
Is it possible? Yes, but not in place, and not easily.
The way I would approach this would be to write a script that would essentially replay the commits the way you want them done, dump the new repo to an svn dumpfile, tweak the dumpfile using svndumptool.py and probably a bit of custom scripting to set dates and authors and such.
You may be able to get svn to help you out some. Try this approach:
Make a copy of your repository so you can work with that and not make a mess for others. Then, in that repository, create /project
/project/trunk
, /project/tags
and /project/branches
directories. Checkout project/trunk. Use svn export
to get rev 1 of your 1.0.0 version into your trunk working copy. Grab the original commit message using svn log --xml
, use svn add
to add all the files, and commit. That gives you your original starting point.
Now, for every commit made to your /version/1.0.0
, merge that changeset into your new trunk, extract the commit message using svn log --xml
, and commit.
Once you run out of commits to 1.0.0, do an svn copy
from trunk
to tags/1.0.0
. Then use svn merge --ignore-ancestry .../version/1.0.0 .../version/1.0.1@xyz
(where xyz is the first commit of the 1.0.1 version). This should get you any changes that happened as part of your release process. (You may need to experiment a bit to get this just right.)
Repeat that process for each of your remaining versions.
Once you are done with that, you have a repository with a better history under /project
, but still have the old ugly history under /versions
. To clean that out, use svn dump project
to create a dumpfile containing just the new history. Now you'll have to do a bit of custom scripting and probably use svndumptool.py
liberally to fixup the commit timestamps and authors in the dumpfile, pulling that information from the svn log --xml
output. You may need to "invent" this information for the tagging commits you did.
Finally, use svn load
to import that dumpfile into a new repository. Verify that all your new, glorious history looks sane, and then use your new repository going forward.
(Oh, and you get bonus points if you set the commit timestamp of your initial svn mkdir /project /project/trunk /project/tags /project/branches
to 1984. ;) )
Disclosure: I've contributed to svndumptool.py
I've been in this situation and I don't think what you want to do is possible without some heavy lifting outside of svn. Unless you REALLY need to have a linear history of your old releases, IMO the most practical thing to do is to simply move those versioned folders under your tags
(or maybe branches
) directory and make sure that releases are tagged correctly from now on. At least you do have the history of changes from the start of each release.
精彩评论