hgcp - Mercurial Cross-Repository copy and move
When refactoring packages, I sometimes find the need to copy some files from one Mercurial repository to another while preserving their history. While this isn't difficult to do once you know how, it isn't a trivial operation. So, I created hgcp. Copying files from source-repo to dest-repo becomes very easy. Here are a few examples:
- hgcp source-repo/features/oddball-feature.txt dest-repo/ (This copies source-repo/features/oddball-feature.txt to dest-repo/features/oddball-feature.txt)
- hgcp -x features source-repo/features/oddball-feature.txt dest-repo/ (This strips off the features subpath, copying source-repo/features/oddball-feature.txt to dest-repo/oddball-feature.txt)
- hgcp -x features source-repo/features/oddball-feature.txt dest-repo/plugins (Copies source-repo/features/oddball-feature.txt to dest-repo/plugins/oddball-feature.txt)
There is also a hgmv command that moves files, instead of just copying them. It otherwise works exactly like the hgcp command.
hgcp can be installed using easy_install: easy_install hgcp
Note to Anyone who doesn't like this feature
In short: that's fine with me. Don't use it.
You don't need to look hard to find many requests for how to do a history-preserving cross-repository copy. Unfortunately, most replies I've seen are rather unhelpful. Here are some responses I've seen:
- That's not a supported workflow.
- If you need this, you're not planning your repository layout very well.
- You shouldn't need to do this very often
- Cross-repository file copying is not a well-defined operation.
- Just copy the file without history, and put a note in the changelog.
- ad nauseum
The basic problem with all of these responses is this: People need to copy or move files between repositories. Subversion encouraged us to put all of our projects in the same repository, so cross-project file copies were trivial. DVCS like Mercurial encourage us to put each project in a separate repository, but fail to provide an easy way to refactor projects. If you find yourself wondering why anyone would ever need to do this, you're in the same boat with hard-core CVS users that wondered why anyone complained that renaming or moving files was a hassle, and that renaming directories was... well, ridiculous. Moving things around is part of refactoring. Projects are split and merged all the time. As far as I'm concerned, cross-repository copy and move is an essential feature.
hgcp doesn't do anything that you couldn't manually do if you wanted. Basically, it uses the Mercurial convert extension. hgcp simply writes a filemap for you, and executes the proper sequence of hg commands. It also allows you to specify paths in a more natural way.
hgcp only works on repositories that are stored on the local filesystem. Hopefully, this is not a large burden, as you can easily check out remote repos, use hgcp, then sync. Also, the source and destination repositories must both be checked out, and have no uncommitted changes.
I've been told that this method doesn't preserve all the history of a file if it's been renamed, especially when the copied/moved file has a long and branchy history. However, this has never caused a problem for me in actual use. Just be aware that when copying or moving a file, you might not be copying it's entire history.
hgcp is licensed under the GNU General Public License version 3
Patches and fixes
I'm happy to accept patches that enhance hgcp or fix bugs. My goal is to keep hgcp as simple as possible, and focused on cross-repository workflows.
Ideas for the Future
- These are all pie-in-the-sky. I won't implement these unless I personally need them, or someone sends me a patch.
- Make sure that all the history of files that have been moved around.
- Work on remote repositories.
- Copy from a specific revision.
- Automatically commit changes. (This makes me nervous, but if I find that I rarely need to look at the changes made by hgcp, it might be useful)
- Turn hgcp into a Mercurial extension?