mirror of
https://github.com/mnauw/git-remote-hg.git
synced 2025-11-01 09:05:48 +01:00
227 lines
8.2 KiB
Plaintext
227 lines
8.2 KiB
Plaintext
git-remote-hg(1)
|
|
================
|
|
|
|
NAME
|
|
----
|
|
git-remote-hg - bidirectional bridge between Git and Mercurial
|
|
|
|
|
|
SYNOPSIS
|
|
--------
|
|
[verse]
|
|
'git clone' hg::<hg repository>
|
|
|
|
|
|
DESCRIPTION
|
|
-----------
|
|
|
|
This tool allows you to transparently clone, fetch and push to and from Mercurial
|
|
repositories as if they were Git ones.
|
|
|
|
To use it you simply need to use the "'hg::'" prefix when specifying a remote URL
|
|
(e.g. when cloning).
|
|
|
|
|
|
EXAMPLE
|
|
-------
|
|
------------
|
|
$ git clone hg::http://selenic.com/repo/hello
|
|
------------
|
|
|
|
|
|
CONFIGURATION
|
|
-------------
|
|
|
|
If you want to see Mercurial revisions as Git commit notes:
|
|
|
|
--------------------------------------
|
|
% git config core.notesRef refs/notes/hg
|
|
--------------------------------------
|
|
|
|
If you are not interested in Mercurial permanent and global branches (aka.
|
|
commit labels):
|
|
|
|
--------------------------------------
|
|
% git config --global remote-hg.track-branches false
|
|
--------------------------------------
|
|
|
|
With this configuration, the 'branches/foo' refs won't appear.
|
|
|
|
If you want the equivalent of `hg clone --insecure`:
|
|
|
|
--------------------------------------
|
|
% git config --global remote-hg.insecure true
|
|
--------------------------------------
|
|
|
|
If you want 'git-remote-hg' to be compatible with 'hg-git', and generate exactly
|
|
the same commits:
|
|
|
|
--------------------------------------
|
|
% git config --global remote-hg.hg-git-compat true
|
|
--------------------------------------
|
|
|
|
If you would like (why?) the old behaviour (export capability)
|
|
where various limitations apply:
|
|
|
|
--------------------------------------
|
|
% git config --global remote-hg.capability-push false
|
|
--------------------------------------
|
|
|
|
In the new behaviour, performing a git push will make git search for and detect
|
|
file rename and copy and turn this into Mercurial commit metadata. To tweak how this
|
|
detection happens, e.g. have it search even more:
|
|
|
|
--------------------------------------
|
|
% git config --global remote-hg.fast-export-options '-M -C -C'
|
|
--------------------------------------
|
|
|
|
The default otherwise is simply `-M -C`. See also e.g.
|
|
https://www.kernel.org/pub/software/scm/git/docs/git-log.html[git-log(1) manpage]
|
|
for more details on the options used to tweak this.
|
|
|
|
As the old refs/hg/... are actually an implementation detail, they are now
|
|
maintained not so visibly. If that, however, would be preferred:
|
|
|
|
--------------------------------------
|
|
% git config --global remote-hg.show-private-refs true
|
|
--------------------------------------
|
|
|
|
Use of shared marks files is the default in a new repo, but can also be enabled
|
|
for an existing repo:
|
|
|
|
--------------------------------------
|
|
% git config --global remote-hg.shared-marks true
|
|
--------------------------------------
|
|
|
|
Note that one should perform a fetch from each remote to properly complete the
|
|
conversion to shared marks files.
|
|
|
|
Mercurial name(s) (of a branch or bookmark) that are not a valid git refname,
|
|
can be ignored by configuring a suitable regular expression, e.g. avoiding
|
|
the invalid '~'
|
|
|
|
--------------------------------------
|
|
% git config --global remote-hg.ignore-name ~
|
|
--------------------------------------
|
|
|
|
Even though the "gitdir" is configurable (using `GIT_DIR`), git does not accept
|
|
certain pathname components, e.g. `.git` or `.gitmodules` (case-insensitive).
|
|
Problems arise if the hg repo contains such pathnames, and recent git versions
|
|
will reject this in a very hard way. So these pathnames are now mapped
|
|
from "hg space" to "git space" in a one-to-one way, where (e.g.)
|
|
`.git[0 or more suffix]` is mapped to `.git[1 or more suffix]` (obviously by
|
|
appending or removing a suffix). The "suffix" in question defaults to `_`,
|
|
but can be configured using
|
|
|
|
--------------------------------------
|
|
% git config --global remote-hg.dotfile-suffix _
|
|
--------------------------------------
|
|
|
|
|
|
NOTES
|
|
-----
|
|
|
|
Remember to run `git gc --aggressive` after cloning a repository, especially if
|
|
it's a big one. Otherwise lots of space will be wasted.
|
|
|
|
The newest supported version of Mercurial is 6.2, the oldest one is 2.4.
|
|
|
|
Pushing branches
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
To push a branch, you need to use the "branches/" prefix:
|
|
|
|
--------------------------------------
|
|
% git checkout branches/next
|
|
# do stuff
|
|
% git push origin 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:
|
|
|
|
--------------------------------------
|
|
git clone hg::https://user:password@bitbucket.org/user/repo
|
|
--------------------------------------
|
|
|
|
You can also use the https://mercurial-scm.org/wiki/SchemesExtension[schemes extension]:
|
|
|
|
--------------------------------------
|
|
[auth]
|
|
bb.prefix = https://bitbucket.org/user/
|
|
bb.username = user
|
|
bb.password = password
|
|
--------------------------------------
|
|
|
|
Finally, you can also use the
|
|
https://pypi.org/project/mercurial_keyring[keyring extension].
|
|
|
|
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]).
|
|
|
|
TECHNICAL DISCUSSION
|
|
--------------------
|
|
|
|
As `git-remote-hg` is a developer tool after all, it might be interesting to know a
|
|
bit about what is going on behind the scenes, without necessarily going into all the
|
|
details.
|
|
|
|
So let's first have a look in the `.git/hg` directory, which typically
|
|
contains a subdirectory for each remote Mercurial repo alias, as well as a `.hg`
|
|
subdirectory. If the Mercurial repo is a local one, it will (again typically)
|
|
only contain a `marks-git` and a `marks-hg` file. If the repo is a remote one,
|
|
then the `clone` contains, well, a local clone of the remote. However, all
|
|
these clones share storage through the `.hg` directory mentioned previously (so
|
|
they do not add up separately). During a fetch/push, the local (proxy) repo is
|
|
used as an intermediate stage. If you would also prefer such an intermediate
|
|
stage for local repos, then setting the environment variable
|
|
`GIT_REMOTE_HG_TEST_REMOTE` will also use a proxy repo clone for a local repo.
|
|
|
|
As for the marks files, `marks-git` is created and used by `git-fast-export`
|
|
and `git-fast-import` and contains a mapping from mark to commit hash, where a
|
|
mark is essentially a plain number. `marks-hg` similarly contains a (JSON) based
|
|
mapping between such mark and hg revision hash. Together they provide for a
|
|
(consistent) view of the synchronization state of things.
|
|
|
|
When operating with shared-marks files, the `marks-git` and `marks-hg` files
|
|
are shared among all repos. As such, they are then found in the `.git/hg`
|
|
directory (rather than a repo subdirectory).
|
|
As there is really only one hg repository
|
|
(the shared storage "union bag" in `.git/hg/.hg`), only 1 set of marks files
|
|
should track the mapping between commit hash and revision hash.
|
|
Each individual remote then only adds some metadata (e.g regarding heads).
|
|
|
|
Upon a fetch, the helper uses the `marks-hg` file to decide what is already present
|
|
and what not. The required parts are then retrieved from Mercurial and turned
|
|
into a `git-fast-import` stream as expected by `import` capability of
|
|
https://www.kernel.org/pub/software/scm/git/docs/gitremote-helpers.html[gitremote-helpers(1)].
|
|
|
|
Upon a push, the helper has specified the `push` capability in the new approach, and
|
|
so git will provide a list of refspecs indicating what should go where.
|
|
If the refspecs indicates a remote delete, it is performed appropriately the Mercurial way.
|
|
If it is a regular push, then git-fast-export is invoked (using the existing `marks-git`)
|
|
and the stream is processed and turned into Mercurial commits (along with bookmarks, etc).
|
|
If the refspec specifies a `src:dest` rename, then the requested remote refname is tracked
|
|
accordingly. If a dry-run is requested, no remote is touched and no (marks) state of
|
|
the run is retained.
|