This page does not meet our wiki style guidelines. Please help improve this page by cleaning up its formatting. |
Keeping a subversion and (read-only) mercurial repository synchronized
(I couldn't find this usage of mercurial anywhere else, that's why I'm writing it up for others here. If anybody else has already written on this, please merge or delete this page...)
I'm currently in the position that I can't convert repositories I work on to mercurial, because my co-workers use subversion to track their work, but still don't want to skip on the functionality of mercurial to keep my personal project tree and to create patches which I can then reapply to the subversion tree in batches (by hand) when needed.
The following is a walk-through to create your own Python tree using mercurial, which stays in sync with the global subversion repository located at python.org. The tree should be read only: you should never push changes back to this tree, because it makes it possible/probable that a merge is necessary (if you don't have commit priviledges to the subversion repository, more on that later on). The former can't be handled programmatically using a simple script. Instead, if you want to publish your own local tree (which you construct in step 2), push the tree to its own location which is disjunct from the synchronized tree; see publishing a tree using http/ssh in this Wiki for more info.
The method
I checked out a current trunk of the python.org subversion repository:
modelnine@phoenix ~ $ svn co http://svn.python.org/projects/python/trunk python ... Ausgecheckt, Revision 45982. modelnine@phoenix ~ $
The script
# # Updates a mercurial tree from corresponding patches in a subversion # repository. Currently this is used to keep a read-only local mercurial # tree in sync with the global Python repository. # Set up... cd $1 export LANG="C" export LC_ALL="C" # Make some globals for easier maintenance. svncurrev=.svn2hg_currev svncurlog=.svn2hg_curlog # Set up mercurial. test -d .hg || hg init echo -e ".svn\n$svncurrev\n$svncurlog" > .hgignore # Get current revisions... new_rev=`svn up | tail -n1 | egrep -o "[0-9]+"` test -f $svncurrev && cur_rev=`cat $svncurrev` || cur_rev="" # Check whether we actually have a new revision at the moment... if [ R${new_rev}R != R${cur_rev}R ] then echo "Updated repository from svn: $cur_rev -> $new_rev" > $svncurlog if [ R${cur_rev}R = RR ] then cur_rev=$new_rev else cur_rev=`expr $cur_rev + 1` fi svn log -v -r $new_rev:$cur_rev >> $svncurlog echo $new_rev > $svncurrev hg commit -A -l $svncurlog > /dev/null 2>&1 fi
The script should be called with one parameter: the location of the subversion repository on disk:
modelnine@phoenix ~ $ ./svn2hg-up python modelnine@phoenix ~ $
Ideally, if you followed the above advice, you should have a mercurial tree in the directory python (alongside the subversion tree), which has one log message (the initial commit).
Keeping in sync
Enter the following line into your crontab (normally, you'll have a crontab -e or similar command...):
0 * * * * test -x /<path to script>/svn2hg-up && /<path to script>/svn2hg-up <path to repository>
After that, svn2hg-up will pull all changes from the subversion repository every hour, and in case the subversion revision changed, will commit the changes to the mercurial repository in the same directory. It currently commits all subversion changes that happened in this time-span as one big commit; it's pretty easy though to extend the script to handle single subversion commits independently.
Using the tree
Duplicate the sync tree using hg clone, and start working on the clone. If you want to merge with the changes that have accumulated so far in subversion, use hg pull from the sync tree to your personal clone.
Pushing changes back
To push back changes, you will need to have commit privileges on the subversion tree. Use hg push to push your changes to the syncing repository, svn add to add files that you have added in the meantime, and svn commit to commit the changes to the subversion repository. If you don't have commit privileges, you'd better not do this to the sync tree (as said before), as hg2svn-up might not be able to sync your tree anymore...