This popped up on my schedule once again today, so I thought I better save it here – JIC.
The goal is simple: project grew big, some parts got a job and moved to LA are big enough to be developed separately. However it’d be better to move them along with their history. Luckily, hg can get you there, with a little to no sweat. Here’s the deal.
First, you need the convert extension enabled. http://mercurial.selenic.com/wiki/ConvertExtension (that’s where extra details are) says it should be
[extensions] hgext.convert=
in your ~/.hgrc (or wherever level you keep your Mercurial configuration at), but mine has
[extensions] convert=
So… go figure yourself.
Then, you need to get a list of what you would like relocated and save it to some file, each line starting with “include” (you can also do “exclude” if you need some inner parts excluded). Like this (I’m using some real name from project so I could share it with colleagues. Names are pretty vague though, so no confidentiality breach involved):
airhydra:uslicer halien$ cat /tmp/targets include API/REST include Scheduler include UI/lib
if you need to rename some directories in new repository, you can do that with adding “rename olddir newdir” (that should go after “include” list) – for instance,
airhydra:uslicer halien$ cat /tmp/targets include API/REST include Scheduler include UI/lib rename Scheduler Backend/Scheduler
Now, run that convert command, pointing it to a file with targets/actions, source and target (temporary) directory. In my case, source is current directory. Remember: considering on repository size, it could go on for some time and crap in your console like a bloody deranged elephant. Example (crap wiped off):
airhydra:uslicer halien$ hg convert --filemap /tmp/targets ./ /tmp/TempRepo initializing destination /tmp/TempRepo repository scanning source... sorting... converting... 15855 add data validation 15854 update data validation 15853 add API placeholder 15852 add test data 15851 Initial API skeleton (...loads of crap...)
Now go to the repository you need those changes at. Here starts the artificial part – I initialized a new repo called NewWorld, but you should create and clone (or, well, just init, if that’s the case) yours in advance. In that repo, pull from the temporary repository you’ve dumped changes into:
airhydra:NewWorld halien$ hg pull -f /tmp/TempRepo pulling from /tmp/TempRepo requesting all changes adding changesets adding manifests adding file changes added 5809 changesets with 7074 changes to 364 files (+166 heads) (run 'hg heads' to see heads)
Big one, eh? That’s just a fraction. Deserved a move long ago.
If your repository is new, just update to the default branch (or whatever you fancy). If you’re pulling changes into existing one, do a merge. And if the existing repository had some branches named similarly to those available in pulled changeset, you need to resolve conflicts. Which is ugly, so I wish you don’t have to. Or it might be one of the rare cases to justify push -f (given you don’t care much of those branches).
Aaaand… that should be it:
airhydra:NewWorld halien$ ls API Backend UI airhydra:NewWorld halien$ hg branches|wc -l 918 airhydra:NewWorld halien$ hg hi|grep changeset:|wc -l 5809
It probably could be done in some more, ehm, (cruelly) sophisticated way through pipes – but I don’t want to bother. This one’s good enough for the case.