mercurial: Transplanting changes from one repository to another
Maybe this is obvious to those of you who's been using mercurial, but it this wans't certainly obvious to me, so here it goes...
Here's situation I was in this morning. We are trying to move some of our code in CVS into hg. Now, it would be nice if this can be done quickly and painlessly, but as you'd expect with any such conversion tool, it turns out that the conversion process didn't quite work out very well.
So one idea I had was that, perhaps we can grab the head of CVS, create a fresh hg repo X from it (at this point we lose all history), then get going. We can then try to create another hg repository Y with full history imported from CVS, while the rest of the development team is happily hacking with the new repository X. This would work nicely if changes made in X can be then later brought over to Y. This would reduce the down time to minimum.
So, how can we do this?
The normal push/pull doesn't work becaues X and Y don't share any common changeset. bundling changes in X then bringing them to Y also didn't work, presumably for the same reason:
$ cd x
$ hg bundle --base baseline bundle.file
$ cd ../y
$ hg unbundle ../x/bundle.file
abort: unknown parent a744b189089c!
The trick was to use import/export. For some reason this didn't work on my cygwin (it chokes with "abort: patch command failed: exited with status 1" without any other error message), but on my Linux system it worked. Another key was to create one file per one changeset. So the command that worked was:
$ cd x
$ hg export -o change%r 1:tip
$ cd ../y
$ hg import ../x/change*
Note that "1:tip" portion needs to be the range of changeset that you want to copy.
This not only recreates the complete changeset exactly, but it also manages to preserve the date of commit, the user who committed it, and commit message. How nice.
Now, I don't know how it works if changes made in X are more complex — such as involving branching and merging, binary files, etc.