#pragma section-numbers 2 = Subversion-to-Mercurial How-To = This is a quick "how-to" on how to use Mercurial to work locally with a remote read-only Subversion repository. Many open-source projects now use Subversion, and rather than allow write access to their repository they accept patches in "universal diff" format. This how-to will show you how to set up your own Mercurial [[Repository|repositories]] to mirror the Subversion repositories, and to generate diffs against the current Subversion revision. For a lengthier discussion targeted at Mercurial novices, please see my original blog posting "How To Use Mercurial For Local Source Code Management With A Public Subversion Server" at [[http://www.momentaryfascinations.com/]]. <> == The basic approach == 1. Check the tree out from Subversion and in to a Mercurial repository. This branch will always be read-only. 1. Clone that tree to a second repository. This is the tree where you do your work. 1. When there are updates to the Subversion tree, update your read-only tree and pull the changes into your work tree. 1. When it's time to make your patch, diff your work tree to the read-only tree. === Check out from Subversion, check in to Mercurial === The first goal is to download a copy of the current Subversion tree and check it into a repository I'll call {{{trunk}}}. I'll use the Python "py3k" branch as my example Subversion repository. First run: {{{ % svn co http://svn.python.org/projects/python/branches/p3yk trunk % hg init trunk % cd trunk % hg branch trunk }}} Next create a {{{.hgignore}}} in that directory and add the following lines: {{{ syntax: glob .svn }}} '''Tip:''' If you want to add more stuff to your {{{.hgignore}}}, do it here in the {{{trunk}}} repository. That way it won't show up later when you run diffs against the original. Now check in everything: {{{ % hg add % hg ci }}} The {{{trunk}}} branch is now ready. This branch should ''only'' be used as a mirror of the Subversion repository, and should otherwise be treated as "read-only". === Branch to your work repository === I'm doing work on concatenation, so I'll create a [[Branch|branch]] called {{{concat}}} where I'll create my patch. {{{ % cd .. % hg clone trunk concat % cd concat % hg branch concat }}} The {{{concat}}} branch is now ready for work; you may start editing and checking in all you like. === Updating Your Branch From Subversion === Here's how to pull changes from the Subversion repository into your workspace. First, update your {{{trunk}}} branch from the Subversion repository: {{{ % cd trunk % svn update % hg addremove % hg ci }}} Next, pull those changes into your {{{concat}}} branch: {{{ % cd ../concat % hg pull ../trunk % hg merge }}} '''Tip:''' it's probably easiest to do this when you don't have any outstanding edits. === Generating A Patch === What you really want to do is generate a local "diff" against the tip revision in the trunk branch. Because we named our branches, and we have all the {{{trunk}}} revisions in {{{concat}}}, this is easy: {{{ % cd concat % hg diff -r trunk -r tip }}} == Stacking Patches == It's easy to make a patch that's dependent on another patch; just {{{hg clone}}} from your work branch instead of the Subversion mirror branch. For instance, I want to make a {{{slice}}} patch that depends on my {{{concat}}} patch. I do this: {{{ % hg clone concat slice % cd slice % hg branch slice }}} All the other steps work like the above, except you use the {{{concat}}} branch instead of the {{{trunk}}} branch. Run {{{hg pull ../concat}}} to update the slice branch, and {{{hg diff -r concat -r tip}}} to generate a patch. (Or {{{hg diff -r trunk -r tip}}} to generate a cumulative "rollup" patch with the changes from both {{{concat}}} ''and'' {{{slice}}}!) == Why Not Queues? == You can use [[MqExtension|Mercurial's queues extension]] to achieve much the same result. There are several advantages of using queues: there are fewer steps involved in several of the processes, and because you only need one repository you can use less disk space. The main disadvantage is that you can't easily track the history of commits to your patches. ---- CategoryHowTo