qshinoの日記

Powershell関係と徒然なこと

Mercurial to git

mercurial to git

全体の流れ

  1. git 変換ツール入手
  2. mercurial authors ファイル作成、手修正
  3. git変換
  4. git確認

authors file手修正以外は、コマンドを打つだけ。

実行手順

# params

toolsrc=https://repo.or.cz/r/fast-export.git
tool=/tmp/fast-export
hgrepo=/opt/hg/wk
newhgrepo=/opt/hg/newwk
authfile=/tmp/autors
gittepo=/tmp/gitrepo
gitremote=git@gitsv:gitrepo.git

# start operations

# get tool , fast-export

git clone $toolsrc  $tool

hg clone $hgrepo $newhgrepo

cd $newhgrepo

hg log | grep user: | sort | uniq | sed 's/user: *//' > $authfile

# edit $authfile

git init $gitrepo
cd $gitrepo

# following will take time

$tool/hg-fast-export.sh -r $newhgrepo -A $authfile

# confirm

git shortlog -sn

# push to remote repository

git remote add $gitremote

git push origin --all

edit authors

元ファイル

foo
bar

編集後

foo=foo <foo@foo.com>
bar=bar <bar@bar.com>

Details

Mercurial

Mercurial と Git は、バージョンの表現方法がよく似ており、また Git の方が少し柔軟性が高いので、Mercurial から Git へのリポジトリの変換は非常に素直に行えます。変換には "hg-fast-export" というツールを使用します。このツールは次のコマンドで取得できます。

$ git clone http://repo.or.cz/r/fast-export.git /tmp/fast-export

変換の最初のステップとして、変換の対象となる Mercurial リポジトリのクローンを取得します。

$ hg clone <remote repo URL> /tmp/hg-repo

次のステップでは、author マッピングファイルを作成します。 チェンジセットの author フィールドへ指定できる内容は、Git より Mercurial の方が制限がゆるいので、これを機に内容を見直すのがよいでしょう。 author マッピングファイルは、bash シェルなら次のワンライナーで生成できます。

$ cd /tmp/hg-repo $ hg log | grep user: | sort | uniq | sed 's/user: *//' > ../authors

プロジェクトの歴史の長さによりますが、このコマンドの実行には数秒かかります。実行後には、 /tmp/authors ファイルが次のような内容で作成されているはずです。

bob bob@localhost bob <bob@company.com> bob jones <bob <AT> company <DOT> com> Bob Jones <bob@company.com> Joe Smith <joe@company.com>

この例では、同じ人(Bob)がチェンジセットを作成したときの名前が4パターンあり、そのうち1つだけが標準に合った書き方で、また別の1つは Git のコミットとしては完全に無効なように見えます。 hg-fast-export では、このような状態を修正する場合、修正したい行の末尾に ={修正後の氏名とメールアドレス} を追加し、変更したくないユーザ名の行はすべて削除します。 すべてのユーザ名が正しいなら、このファイルは必要ありません。 この例では、ファイルの内容を次のようにします。

bob=Bob Jones <bob@company.com> bob@localhost=Bob Jones <bob@company.com> bob <bob@company.com>=Bob Jones <bob@company.com> bob jones <bob <AT> company <DOT> com>=Bob Jones <bob@company.com>

次のステップでは、新しい Git リポジトリを作成して、エクスポート用スクリプトを実行します。

$ git init /tmp/converted $ cd /tmp/converted $ /tmp/fast-export/hg-fast-export.sh -r /tmp/hg-repo -A /tmp/authors

hg-fast-export に対して、 -r フラグで、変換の対象となる Mercurial リポジトリの場所を指定しています。また、 -A フラグで、author マッピングファイルの場所を指定しています。 このスクリプトは、Mercurial のチェンジセットを解析して、Git の "fast-import" 機能(詳細はまた後で説明します)用のスクリプトへ変換します。 これには少し時間がかかります(ネットワーク経由の場合と比べれば かなり 速いですが)。出力は非常に長くなります。

$ /tmp/fast-export/hg-fast-export.sh -r /tmp/hg-repo -A /tmp/authors Loaded 4 authors master: Exporting full revision 1/22208 with 13/0/0 added/changed/removed files master: Exporting simple delta revision 2/22208 with 1/1/0 added/changed/removed files master: Exporting simple delta revision 3/22208 with 0/1/0 added/changed/removed files […] master: Exporting simple delta revision 22206/22208 with 0/4/0 added/changed/removed files master: Exporting simple delta revision 22207/22208 with 0/2/0 added/changed/removed files master: Exporting thorough delta revision 22208/22208 with 3/213/0 added/changed/removed files Exporting tag [0.4c] at [hg r9] [git :10] Exporting tag [0.4d] at [hg r16] [git :17] […] Exporting tag [3.1-rc] at [hg r21926] [git :21927] Exporting tag [3.1] at [hg r21973] [git :21974] Issued 22315 commands git-fast-import statistics: --------------------------------------------------------------------- Alloc'd objects: 120000 Total objects: 115032 ( 208171 duplicates ) blobs : 40504 ( 205320 duplicates 26117 deltas of 39602 attempts) trees : 52320 ( 2851 duplicates 47467 deltas of 47599 attempts) commits: 22208 ( 0 duplicates 0 deltas of 0 attempts) tags : 0 ( 0 duplicates 0 deltas of 0 attempts) Total branches: 109 ( 2 loads ) marks: 1048576 ( 22208 unique ) atoms: 1952 Memory total: 7860 KiB pools: 2235 KiB objects: 5625 KiB --------------------------------------------------------------------- pack_report: getpagesize() = 4096 pack_report: core.packedGitWindowSize = 1073741824 pack_report: core.packedGitLimit = 8589934592 pack_report: pack_used_ctr = 90430 pack_report: pack_mmap_calls = 46771 pack_report: pack_open_windows = 1 / 1 pack_report: pack_mapped = 340852700 / 340852700 --------------------------------------------------------------------- $ git shortlog -sn 369 Bob Jones 365 Joe Smith

作業はこれだけです。 すべての Mercurial のタグは Git のタグに変換され、 Mercurial のブランチとブックマークは Git のブランチに変換されています。 これで、リポジトリを新しいサーバ側へプッシュする準備が整いました。

$ git remote add origin git@my-git-server:myrepository.git $ git push origin --all

ref