'\" t
.\" Title: git-remote-hg
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.79.1
.\" Date: 02/09/2019
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "GIT\-REMOTE\-HG" "1" "02/09/2019" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\" http://bugs.debian.org/507673
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
git-remote-hg \- bidirectional bridge between Git and Mercurial
.SH "SYNOPSIS"
.sp
.nf
\fIgit clone\fR hg::
.fi
.SH "DESCRIPTION"
.sp
This tool allows you to transparently clone, fetch and push to and from Mercurial repositories as if they were Git ones\&.
.sp
To use it you simply need to use the "\fIhg::\fR" prefix when specifying a remote URL (e\&.g\&. when cloning)\&.
.SH "EXAMPLE"
.sp
.if n \{\
.RS 4
.\}
.nf
$ git clone hg::http://selenic\&.com/repo/hello
.fi
.if n \{\
.RE
.\}
.SH "CONFIGURATION"
.sp
If you want to see Mercurial revisions as Git commit notes:
.sp
.if n \{\
.RS 4
.\}
.nf
% git config core\&.notesRef refs/notes/hg
.fi
.if n \{\
.RE
.\}
.sp
If you are not interested in Mercurial permanent and global branches (aka\&. commit labels):
.sp
.if n \{\
.RS 4
.\}
.nf
% git config \-\-global remote\-hg\&.track\-branches false
.fi
.if n \{\
.RE
.\}
.sp
With this configuration, the \fIbranches/foo\fR refs won\(cqt appear\&.
.sp
If you want the equivalent of hg clone \-\-insecure:
.sp
.if n \{\
.RS 4
.\}
.nf
% git config \-\-global remote\-hg\&.insecure true
.fi
.if n \{\
.RE
.\}
.sp
If you want \fIgit\-remote\-hg\fR to be compatible with \fIhg\-git\fR, and generate exactly the same commits:
.sp
.if n \{\
.RS 4
.\}
.nf
% git config \-\-global remote\-hg\&.hg\-git\-compat true
.fi
.if n \{\
.RE
.\}
.sp
If you would like (why?) the old behaviour (export capability) where various limitations apply:
.sp
.if n \{\
.RS 4
.\}
.nf
% git config \-\-global remote\-hg\&.capability\-push false
.fi
.if n \{\
.RE
.\}
.sp
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:
.sp
.if n \{\
.RS 4
.\}
.nf
% git config \-\-global remote\-hg\&.fast\-export\-options \*(Aq\-M \-C \-C\*(Aq
.fi
.if n \{\
.RE
.\}
.sp
The default otherwise is simply \-M \-C\&. See also e\&.g\&. git\-log(1) manpage for more details on the options used to tweak this\&.
.sp
As the old refs/hg/\&... are actually an implementation detail, they are now maintained not so visibly\&. If that, however, would be preferred:
.sp
.if n \{\
.RS 4
.\}
.nf
% git config \-\-global remote\-hg\&.show\-private\-refs true
.fi
.if n \{\
.RE
.\}
.sp
Use of shared marks files is the default in a new repo, but can also be enabled for an existing repo:
.sp
.if n \{\
.RS 4
.\}
.nf
% git config \-\-global remote\-hg\&.shared\-marks true
.fi
.if n \{\
.RE
.\}
.sp
Note that one should perform a fetch from each remote to properly complete the conversion to shared marks files\&.
.sp
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 \fI~\fR
.sp
.if n \{\
.RS 4
.\}
.nf
% git config \-\-global remote\-hg\&.ignore\-name ~
.fi
.if n \{\
.RE
.\}
.SH "NOTES"
.sp
Remember to run git gc \-\-aggressive after cloning a repository, specially if it\(cqs a big one\&. Otherwise lots of space will be wasted\&.
.sp
The oldest version of Mercurial supported is 1\&.9\&. For the most part 1\&.8 works, but you might experience some issues\&.
.SS "Pushing branches"
.sp
To push a Mercurial named branch, you need to use the "branches/" prefix:
.sp
.if n \{\
.RS 4
.\}
.nf
% git checkout branches/next
# do stuff
% git push origin branches/next
.fi
.if n \{\
.RE
.\}
.sp
All the pushed commits will receive the "next" Mercurial named branch\&.
.sp
\fBNote\fR: Make sure you don\(cqt have remote\-hg\&.track\-branches disabled\&.
.SS "Cloning HTTPS"
.sp
The simplest way is to specify the user and password in the URL:
.sp
.if n \{\
.RS 4
.\}
.nf
git clone hg::https://user:password@bitbucket\&.org/user/repo
.fi
.if n \{\
.RE
.\}
.sp
You can also use the schemes extension:
.sp
.if n \{\
.RS 4
.\}
.nf
[auth]
bb\&.prefix = https://bitbucket\&.org/user/
bb\&.username = user
bb\&.password = password
.fi
.if n \{\
.RE
.\}
.sp
Finally, you can also use the keyring extension\&.
.SH "CAVEATS"
.sp
The only major incompatibility is that Git octopus merges (a merge with more than two parents) are not supported\&.
.sp
Mercurial branches and bookmarks have some limitations of Git branches: you can\(cqt have both \fIdev/feature\fR and \fIdev\fR (as Git uses files and directories to store them)\&.
.sp
Multiple anonymous heads (which are useless anyway) are not supported; you would only see the latest head\&.
.sp
Closed branches are not supported; they are not shown and you can\(cqt close or reopen\&. Additionally in certain rare situations a synchronization issue can occur (Bug #65)\&.
.SH "TECHNICAL DISCUSSION"
.sp
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\&.
.sp
So let\(cqs 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\&.
.sp
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\&.
.sp
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)\&.
.sp
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 gitremote\-helpers(1)\&.
.sp
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\&.