Mercurial to Git, solving "invalid-email-address"
17 October, 2011If you've used the hg-git plugin to migrate code from Hg to Git, you probably would have come across the wonderful invalid-email-address error when pushing. Git relies on email addresses for identity, whereas Hg is happy to use just usernames so when you convert it the author/commiter email addresses are left as none@none.
We (MahApps, that is) decided to migrate a bunch of libraries we had on Codeplex and BitBucket to a single service, and given the undeniable popularity of GitHub*, chose that rather than BitBucket. There are other reasons too, such as the Jekyll powered GitHub Pages means MahApps.com is now hosted on GitHub or the far better "organisations" support. While there weren't dozens of libraries, if you have to do something more than once, you should automate it, and here we have a script that will clone, bookmark, export to git, rewrite history, and push to the new git source.
Requirements: Hg, Hg-Git, Git Bash
#!/bin/sh
hg clone $2 $1
cd $1
hg bookmark -r default master
hg gexport
mv .hg/git .git
rm -rf .hg
git init
git checkout master -f
git filter-branch --env-filter '
an="$GIT_AUTHOR_NAME"
am="$GIT_AUTHOR_EMAIL"
cn="$GIT_COMMITTER_NAME"
cm="$GIT_COMMITTER_EMAIL"
if [ "$GIT_AUTHOR_NAME" = "user1" ]
then
cn="user1"
cm="user1s@email"
an="user1"
am="user1s@email"
fi
if [ "$GIT_AUTHOR_NAME" = "user2" ]
then
cn="users2name"
cm="user2s@email"
an="users2name"
am="user2s@email"
fi
export GIT_AUTHOR_NAME="$an"
export GIT_AUTHOR_EMAIL="$am"
export GIT_COMMITTER_NAME="$cn"
export GIT_COMMITTER_EMAIL="$cm"
'
git remote add origin $3
git push origin master
Usage
./hg_git_with_fixes <name> <hg clone url> <git push url>
ie
./hg_git_with_fixes mahappsmetro https://bitbucket.org/aeoth/mahapps.metro [email protected]:MahApps/MahApps.Metro.git
Caveats
- You will have to manually edit this script to include the updated user information. Yes, you have to do this for each user
- If you want more than the default branch pushed, you're going to have to add bookmarks for all of those, and perhaps adjust filter-branch to operate on
-all - The name (first value) is needed for a temporary directory to operate in.

