mirror of
https://github.com/mnauw/git-remote-hg.git
synced 2025-10-29 23:55:48 +01:00
These changes involve a port to python3. These can mostly be discarded, as such port has already been done in an alternative way, which supports both v2 and v3.
213 lines
7.5 KiB
Plaintext
213 lines
7.5 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 ~
|
|
--------------------------------------
|
|
|
|
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.
|