'\" 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\&.