'git-remote-hg' is the semi-official Mercurial bridge from Git project, once installed, it allows you to clone, fetch and push to and from Mercurial repositories as if they were Git ones:
To enable this, simply add the 'git-remote-hg' script anywhere in your $PATH
:
In Windows, you also need to put and an NTFS symbolic link named python2.exe
somewhere
on your $PATH
pointing to your Python 2 executable:
That's it :)
Obviously you will need Mercurial installed.
At present, this "working copy"/fork <<add-features, adds the following features>> (and I would prefer it is indeed rather a "working copy" to be appropriately merged upstream):
refs/hg/...
by keeping these implementation details really privateSee sections below or sidemarked notes for more details.
== Configuration ==
If you want to see Mercurial revisions as Git commit notes:
If you are not interested in Mercurial permanent and global branches (aka. commit labels):
With this configuration, the 'branches/foo' refs won't appear.
If you want the equivalent of 'hg clone --insecure':
If you want 'git-remote-hg' to be compatible with 'hg-git', and generate exactly the same commits:
== Notes ==
Remember to run git gc --aggressive
after cloning a repository, specially if
it's a big one. Otherwise lots of space will be wasted.
The oldest version of mercurial supported is 1.9. For the most part 1.8 works, but you might experience some issues.
=== Pushing branches ===
To push a branch, you need to use the "branches/" prefix:
% git checkout branches/next
All the pushed commits will receive the "next" Mercurial named branch.
Note: Make sure you don't have +remote-hg.track-branches+ disabled.
=== Cloning HTTPS ===
The simplest way is to specify the user and password in the URL:
You can also use the http://mercurial.selenic.com/wiki/SchemesExtension[schemes extension]:
Finally, you can also use the https://pypi.python.org/pypi/mercurial_keyring[keyring extension].
However, some of these features require very new versions of 'git-remote-hg', so you might have better luck simply specifying the username and password in the URL.
=== Submodules ===
Hg repositories can be used as git submodule, but this requires to allow the hg procotol to be used by git submodule commands:
Or adding manually the following to your git configuration file:
This can be done per-repository, every time after a clone, or globally in the global .gitconfig (using the --global command-line option).
=== Caveats ===
The only major incompatibility is that Git octopus merges (a merge with more than two parents) are not supported.
Mercurial branches and bookmarks have some limitations of Git branches: you can't have both 'dev/feature' and 'dev' (as Git uses files and directories to store them).
Multiple anonymous heads (which are useless anyway) are not supported; you would only see the latest head.
Closed branches are not supported; they are not shown and you can't close or reopen. Additionally in certain rare situations a synchronization issue can occur (https://github.com/felipec/git/issues/65[Bug #65]).
[[limitations]] Limitations of the remote-helpers' framework apply. In particular, these commands don't work:
git push origin :branch-to-delete
Another limitation is that if git log
reports a rename, this will not survive
the push and Mercurial will not be aware of a rename (and similarly so for copy).
Though Mercurial would know about it if you manually ran git-format-patch
followed by a hg apply -s
, which is not the nice way to go obviously.
Actually, scratch the limitations above ascribed to the remote-helpers framework. They are not limitations of the framework, but are due to how the original implementation of 'git-remote-hg' interacts with it. Using the remote-helpers framework in only a slightly different way has none of the above limitations. See the <<no-limitations, relevant section>> below for more details.
== Other projects ==
There are other 'git-remote-hg' projects out there, do not confuse this one, this is the one distributed officially by the Git project (though actually no longer so nowadays):
For a comparison between these and other projects go https://github.com/felipec/git/wiki/Comparison-of-git-remote-hg-alternatives[here].
[[no-limitations]] == Limitations (or not) ==
If interested in some of technical details behind this explanation, then also see the relevant section in 'git-remote-hg' manpage. Otherwise, the general idea is presented here.
More precisely and simply, the <<limitations, mentioned limitations>> are indeed
limitations of the export
capability of
https://www.kernel.org/pub/software/scm/git/docs/gitremote-helpers.html[gitremote-helpers(1)]
framework. However, the framework also supports a push
capability and when this
is used appropriately in the remote helper the aforementioned limitations do not apply.
In the case of export
capability, git-core will internally invoke git-fast-export
and the helper will process this data and hand over generated changesets to Mercurial.
In the case of push
capability, git informs the helper what (refs) should go where,
and the helper is free to ponder about this and take the required action, such as
to invoke git-fast-export
itself (with suitable options) and process its output
the same way as before (and over to Mercurial).
And so;
git push origin :branch-to-delete
will delete the bookmark branch-to-delete
on remotegit push --dry-run origin branch
will not touch the remote
(or any local state, except for local helper proxy repo)git push origin old:new
will push old
onto new
in the remotegit push origin <history-with-copy/rename>
will push copy/rename aware Mercurial revisions[[add-features]] == Additional Features ==
=== Miscellaneous Tweaks ===
Other than <<no-limitations, removing the limitations>> as mentioned above,
a number of issues (either so reported in
https://github.com/felipec/git-remote-hg/issues[issue tracking] or not) have been
addressed here, e.g. notes handling, fetch --prune
support, correctly fetching
after a strip
on remote repo, tracking remote changes to import (if any) in a
safe, robust and efficient way, etc. Some of these have been highlighted above.
refs/hg/...
refs are really an implementation detail
that need not clutter up the (visible) ref space. So, in as much as they
are still relevant, these are now kept elsewhere out of sight.
If somehow your workflow relies on having these in the old place:strip
on a remote.
This shared-marks-files behaviour is the default on a fresh repo clone. It can
also be enabled on an existing one by the following setting.Note, however, that one should then perform a fetch from each relevant remote to fully complete the conversion (prior to subsequent pushing).
man git-check-ref-format
for a rather involved set of rules.
Moreover, while a slash /
is allowed, it is not supported to have both a parent
and parent/child
branch (though only the latter is allowed). Even though
it is not quite (bidirectionally) safe, a (percentage) URL encoding
(with some additional twist) is performed to obtain sane git refnames, at least
so for most cases. If some nasty cases still slip through, then likely only
a few instances (out of a whole Mercurial repo) are
problematic. This could be handled by a single-branch clone and/or configuring
a suitable refspec. However, it might be more convenient to simply filter out a
few unimportant pesky cases, which can be done by configuring a regural
expression in following setting:Recall also that a config setting can be provided at clone time
(command line using --config
option).
By default, for backwards compatibility with earlier versions, git-remote-hg removes quotation marks from git usernames (e.g. 'Raffaello "Raphael" Sanzio da Urbino raphael@example.com' would become 'Raffaello Raphael Sanzio da Urbino raphael@example.com'). This breaks round-trip compatibility; a git commit by an author with quotes would become an hg commit without, and if re-imported into git, would get a different SHA1.
To restore round-trip compatibility (at the cost of backwards compatibility with commits converted by older versions of git-remote-hg), turn 'remote-hg.remove-username-quotes' off.
=== Helper Commands ===
Beyond that, a 'git-hg-helper' script has been added that can aid in the git-hg interaction workflow with a number of subcommands that are not in the purview of a remote helper. This is similar to e.g. 'git-svn' being a separate program altogether. These subcommands
git-remote-hg
metadata marks$PATH
accessible) next to 'git-remote-hg'.
Following git alias is probably also convenient as it allows invoking the helper
as git hg
:With that in place, running git hg gc <remote>
after initial fetch from (large)