از آنجا که Mercurial و Git مدلهای نسبتاً مشابهی برای نمایش نسخهها دارند و Git تا حدی انعطافپذیرتر است، تبدیل یک مخزن از Mercurial به Git نسبتاً سرراست است و از ابزاری به نام "hg-fast-export" استفاده میکند که باید یک نسخه از آن را داشته باشید:
$ git clone https://github.com/frej/fast-export.gitاولین گام در تبدیل، گرفتن یک کلون کامل از مخزن Mercurial است که میخواهید تبدیل کنید:
$ hg clone <remote repo URL> /tmp/hg-repoگام بعدی ایجاد یک فایل نگاشت نویسنده است.
Mercurial در مورد مقداری که در فیلد نویسنده برای changesetها قرار میدهد کمی بزرگسروتر از Git است، بنابراین این زمان خوبی است برای پاکسازی.
تولید این فایل با یک فرمان تکخطی در شل 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>در این مثال، یک فرد واحد (باب) changesetهایی را تحت چهار نام مختلف ایجاد کرده است؛ یکی از آنها در واقع درست به نظر میرسد و یکی از آنها برای یک commit در Git کاملاً نامعتبر خواهد بود.
Hg-fast-export به ما اجازه میدهد این را با تبدیل هر خط به یک قاعده اصلاح کنیم: "<input>"="<output>"، که یک <input> را به یک <output> نگاشت میکند.
درون رشتههای <input> و <output>، تمام توالیهای فرار (escape sequences) که توسط انکودینگ Python string_escape شناخته میشوند پشتیبانی میشوند.
اگر فایل نگاشت نویسنده شامل یک <input> مطابق نباشد، آن نویسنده بدون تغییر به Git ارسال خواهد شد.
اگر همه نامهای کاربری درست به نظر برسند، اصلاً به این فایل نیازی نخواهیم داشت.
در این مثال، میخواهیم فایل ما شبیه به این باشد:
"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>"همین نوع فایل نگاشت را میتوان برای تغییر نام شاخهها و تگها هم استفاده کرد، وقتی نام Mercurial توسط Git مجاز نیست.
گام بعدی ایجاد مخزن جدید Git و اجرای اسکریپت export است:
$ git init /tmp/converted
$ cd /tmp/converted
$ /tmp/fast-export/hg-fast-export.sh -r /tmp/hg-repo -A /tmp/authorsپرچم `-r` به `hg-fast-export` میگوید مخزن مرکوریال که میخواهیم تبدیل کنیم کجا قرار دارد، و پرچم `-A` به آن میگوید فایل نگاشت نویسندهها کجا قرار دارد (فایلهای نگاشت شاخه و تگ بهترتیب با پرچمهای `-B` و `-T` مشخص میشوند). اسکریپت تغییرمجموعههای مرکوریال را پارس کرده و آنها را به اسکریپتی برای قابلیت `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تقریباً همین بود. تمام تگهای مرکوریال به تگهای گیت تبدیل شدهاند و شاخهها و بوکمارکهای مرکوریال به شاخههای گیت تبدیل شدهاند. حالا آمادهاید که مخزن را به محل جدیدش روی سرور ارسال کنید:
$ git remote add origin git@my-git-server:myrepository.git
$ git push origin --all