Update: Added optional code to show how you would put feature in a branch first rather than just committing directly to the trunk.
#!/bin/bash # # Merging a separate feature repository into a folder in an SVN repository by # way of two hg repositories. # # Inspired by: http://hgtip.com/tips/advanced/2009-11-17-combining-repositories/ # # Requires: # subversion installed # convert extension # mq extension (for strip) # rebase extension # hgsubversion extension # # We have the following four repositories: # SVN repo hg-svn hg-svn-work # feature # # SVN repo: company subversion repo on remote server, https://ip/svn # hg-svn: local developer copy of SVN repo using hgsubversion # hg-svn-work: a local working copy of hg-svn. (Why? In my case, # it's inside a Linux virtual machine running on a Mac. # hg-svn is on the Mac.) # feature: a completely separate hg repository containing some new # program developed in isolation. (Perhaps a contract job?) # # Our goal is to put feature and all of its history into SVN, but we must # place it into a sub-folder /new/feature. # # Steps: # 1. Use hg convert to re-map feature/* to feature/new/feature/*. # 2. Hg pull the converted feature repo into hg-svn-work. # 3. Hg rebase the pulled feature onto the previous tip. # 4. Hg push the changes to hg-svn # 5. Hg push from hg-svn into the SVN repo. # 6. Hg pull changes from hg-svn into hg-svn-work # 7. Hg strip the pulled feature changesets from step 2. # # Using a feature branch: # It would be nice to put feature into its own subversion branch # first and then merge it back into the trunk. If you'd like to do # this, enable USE_A_BRANCH below. USE_A_BRANCH=1 # enable = 1 # Example: # Turn on debugging so we can see the commands as they're issued. set -x # Clean up after any previous run. rm -rf feature_test mkdir feature_test cd feature_test # Create a "company" SVN repository. svnadmin create SVN svn co file://`pwd`/SVN SVN_temp # Put something in the SVN repository or we won't be able # to see why some of the steps are necessary. cd SVN_temp/ svn mkdir trunk tags branches svn ci -m "Initial folders" echo "Company file" > trunk/company.txt svn add trunk/company.txt svn ci -m "Added company.txt" cd .. if [ "$USE_A_BRANCH" = "1" ]; then # Create a feature branch in subversion svn copy file://`pwd`/SVN/trunk file://`pwd`/SVN/branches/feature -m "Added feature branch" fi # Create our first and second level clones of SVN. if [ "$USE_A_BRANCH" = "1" ]; then # Make sure to clone the new branch! hg clone file://`pwd`/SVN/branches/feature hg-svn else hg clone file://`pwd`/SVN/trunk hg-svn fi hg clone hg-svn hg-svn-work # Create a new feature in its own repository. It needs more than one # changeset to show how hgsubversion will rebase after pushing each # changeset. hg init feature cd feature echo "Some text" >> readme.txt hg add readme.txt hg com -m "Added readme.txt" echo "Some more text" >> readme.txt hg com -m "Added more text" cd .. # Create a clone/copy of feature where we move everything into the # subfolder that it needs to be in for the company SVN layout. echo "rename . new/feature" > map.txt hg convert --filemap map.txt feature feature-conv rm map.txt # Pull the converted feature repository into our working # copy of the SVN repository. Save the current tip since we will # need it to rebase. cd hg-svn-work/ OLD_TIP=`hg log --template "{rev}\n" -r tip` hg pull -f ../feature-conv # All of the new changesets start from OLD_TIP + 1. Rebase them on # OLD_TIP. hg rebase --source $(($OLD_TIP + 1)) --dest $OLD_TIP # Push the changes up one level to hg-svn hg push cd .. # Clean up the feature copy. rm -rf feature-conv cd hg-svn/ # Update hg-svn since hgsubversion will not detect any outgoing # changesets otherwise. hg up # Push the changes to SVN. Each changeset pushed will cause a rebase. # If you are pushing a lot of changesets (e.g. I did 85), this will take a # while since the algorithm is O(n^2). The first push of N changesets rebases # N-1 changesets, then the next rebases N-2, etc. It will appear pleasantly # faster as it goes. hg push cd .. # Pull the newly rebased changesets back to our working repository. # Unfortunately, we've now done half of an svn push/rebase here. We need # to manually strip away all of the revisions we pulled from feature-conv # earlier as they've all been duplicated now. cd hg-svn-work/ hg pull hg strip -f -n $(($OLD_TIP + 1)) cd .. cd SVN_temp svn up if [ "$USE_A_BRANCH" = "1" ]; then # Optionally, merge the svn feature branch back to the trunk # Note: I don't know (yet) of a simpler way to do this. DIR=$(dirname $(pwd)) svn merge file://$DIR/SVN/branches/feature trunk svn ci -m "Merging feature branch back to trunk" svn delete branches/feature svn ci -m "Closing feature branch" fi set +x echo "==========================" echo "Results:" find . | egrep -v '\.svn' cd .. # Use the following command to see the log of changes: # svn log -v SVN_temp
Leave a Reply