30

How do I convert a Bitbucket Mercurial repository (Hg repository) to a Git repository? I want to keep branches and commit history.

user984003
  • 23,717
  • 51
  • 158
  • 250

4 Answers4

45

The only way I found to convert a Mercurial repo to Git, while keeping all the branches, was to use GitHub's importer. This was also the easiest since it's all done online. Nothing local to install, no command line stuff.

Main idea

Use Github's importer to convert Bitbucket Mercurial repo to GitHub Git repo. Then import that back into Bitbucket.

The steps

In Bitbucket:

Rename the Mercurial repository that you want to convert (if you want the new Git repo to have the same name as your Mercurial repo did). You do this in Repository Settings. For example, name it projectname_mercurial.

Grab the Clone URL of the repository. (On the repo's main page, click Clone and grab just the URL, like https://username@bitbucket.org/username/projectname )

In Github:

If you don't already have an account, create one https://github.com

Use the GitHub importer https://github.com/new/import

  • Enter the Clone URL from Bitbucket.
  • Give it a name. It doesn't really matter what.
  • Set it to private. Public is default!

NOTE: You can add your password to the URL directly, which will then avoid the need to enter your credentials in the steps below (thanks to @keith-turkowski comment below). So change your bitbucket clone url by adding :password after username, like this: https://username:password@bitbucket.org/username/projectname

Begin Import in Github

WAIT! Do not close the page when it says that you can (We'll email you...). Wait for it to ask you for the repo credentials. This can take several minutes. Then enter the credentials. (Assuming it requires credentials.)

WAIT AGAIN! It's again going to ask for your repo credentials. At least it did for me, every time. (See note above on adding your password directly to URL so it does not ask you.)

Now you wait until it's done. You will get an email.

When it's done, grab the GitHub project URL. It's just the webpage URL when you are on the GitHub project page.

In Bitbucket:

Create a new repository using the "+" > Import > Repository menu option.

  • Enter the GitHub project URL
  • Check "Requires authentication" Enter your GitHub credentials.
  • Enter the new Git repository name (For example, the name of your Mercurial project before you renamed it.)
  • Keep Access level as Private.

In Github:

Delete the imported project: Project's Settings tab > Delete this repository

user984003
  • 23,717
  • 51
  • 158
  • 250
  • 3
    Thank you for this manual. Note that GitHub incorrectly imports commit messages that contain non-ASCII signs. Apparently there's an encoding problem. So the text that used to display correctly in Bitbucket Mercurial repository is going to contain question marks in the new Bitbucket Git repo. – Andrej Repiský Oct 17 '19 at 12:48
  • 1
    I used this solution too, and it works perfectly! Anyway remind that only commits, branches and tags are imported, I lost other data (eg issues and wiki) – Dos Nov 22 '19 at 18:08
  • 1
    This worked perfectly. I tried converting my hg repo to git using hg2git, and there were so many problems that I encountered I wanted to pull my hair out. good loophole. 10/10 – Brandon Feb 14 '20 at 00:09
  • 5
    Seems to work perfectly, although I decided to stop after the input in GitHub succeeded, and I'm just deleting the Bitbucket repo instead. ;-) – GolezTrol Apr 02 '20 at 19:47
  • 1
    I should add that BitBucket by default gives you the SSH url, which doesn't work in GitHub's import. Use the HTTPS url instead. It will also add `hg clone` (or `git clone`) in front of the url, which you must not copy. – GolezTrol Apr 02 '20 at 19:59
  • 2
    Rather than waiting for a credentials prompt, you can just include them directly into the import URL: https://username:password@bitbucket.org/username/projectname – Keith Turkowski May 05 '20 at 06:22
  • 1
    @Dos, you can export and import issues. I tried to edit answer to add that, but edit queue was full... – kokbira Jul 03 '20 at 16:51
  • "Before you remove old mercurial Bitbucket repository, you can export issues and import them to the new one. To do so, enter repository settings > issues > import & export, then export from old repository and import to the new one." – kokbira Jul 03 '20 at 16:51
  • But i did not found a fix for automatic wiki export and import... You can use GitHub to import wikis from projects only for your backup. Then, on new Git repository on Bitbucket, you can add pages on the same old structure and copy and paste from backuped GitHub imported - but you will lost the history of changes. – kokbira Jul 03 '20 at 16:53
7

There's also the hg-git Mercurial plugin with which it's possible to convert HG repos to Git repos.

Here's the relevant part from the readme (section "Usage"):

Hg-Git can also be used to convert a Mercurial repository to Git.  You can use
a local repository or a remote repository accessed via SSH, HTTP or HTTPS.  Use
the following commands to convert the repository (it assumes you're running this
in $HOME).

    $ mkdir git-repo; cd git-repo; git init; cd ..
    $ cd hg-repo
    $ hg bookmarks hg
    $ hg push ../git-repo

The hg bookmark is necessary to prevent problems as otherwise hg-git
pushes to the currently checked out branch confusing Git. This will
create a branch named hg in the Git repository. To get the changes in
master use the following command (only necessary in the first run,
later just use git merge or rebase).

    $ cd git-repo
    $ git checkout -b master hg

Note that hg-git only understands Mercurial bookmarks, not Mercurial branches!
(because it was designed to convert into both directions, and there's no Git equivalent to Mercurial's named branches - Git branches are more like Mercurial bookmarks)

If your Mercurial repository has named branches that you want to keep, you need to create a bookmark for each of them before the conversion.


I tried GitHub's importer (mentioned in the other answer) as well, but liked hg-git better because I have more control over the end result.

What I didn't like about the GitHub importer is that it creates commits with "strange" email adresses.
Even though the commits in the HG repos have the same email adress as my GitHub user, the importer still asks me to map the commits to an existing GitHub user.
And even though I select my own user and the commits in the GitHub UI look like they were made by my user, the actual adresses in the repo (when I clone it) look something like this:

Christian Specht <123456+christianspecht@users.noreply.github.com>

With git-hg, you can create a text file with "mappings" from the existing HG committers to the desired Git committers.
Example from the link:

johnny = John Smith <jsmith@foo.com>
dougie = Doug Johnson <dougiej@bar.com>

So if the HG repository had commits from committer johnny, they will automatically be changed to John Smith <jsmith@foo.com> in the converted Git repository.

Christian Specht
  • 33,837
  • 14
  • 123
  • 176
  • For anyone wanting to convert all currently active branches in to bookmarks for hg-git, you can use this command: `hg branches --active --template "{node} {branch}\n" > .hg\bookmarks` – Eddie Fletcher May 06 '20 at 23:28
1

I found https://github.com/frej/fast-export which correctly migrates Mercurial branches to Git branches (in contrast to hg-git which only works with Mercurial bookmarks).

Fast-export works on a local (copy of the) repo so it's not purely online. Fast-export has instructions how to create a new local Git repo and populate it.

In my case, I had left some multiple branch heads in Mercurial, giving this error:

Error: repository has at least one unnamed head: hg r493

I could use "hg strip 493" or do a merge to get rid of these heads.

I also had to fix the author fields of some commits, using an "authors file" and the -A switch to fast-export to map the ill-formatted author fields, as described in the README.

Afterwards fast-export accepted the repo.

You also need to create a new Bitbucket repository through the Bitbucket web interface.

Then push to Bitbucket. This example sets up using already configured SSH:

git remote add origin git@bitbucket.org:<user_name>/<repo_name>
git push --all origin
Anders Petersson
  • 347
  • 1
  • 10
0

I've heard that this script works. Not sure if it converts branches.

https://bitbucket.org/edrandall/bitbucket-hg-to-git/wiki/Running?fbclid=IwAR1vLCXMvJdYAPA8RygcRpQBdFg8goAmK6-bg_sh3bA__vdstDTM00mw65g

user984003
  • 23,717
  • 51
  • 158
  • 250