Omdat Mercurial and Git een redelijk overeenkomend model hebben om versies te representeren en omdat Git iets flexibeler is, is het converteren van een repository uit Mercurial naar Git minder omslachtig, gebruik makend van een instrument dat "hg-fast-export" heet, waar je een kopie van nodig gaat hebben:
$ git clone https://github.com/frej/fast-export.git
De eerste stap in de conversie is om een volledige kloon van de Mercurial repository die je wilt converteren te maken:
$ hg clone <remote repo URL> /tmp/hg-repo
De volgende stap is om een auteur-mapping bestand te maken.
Mercurial is wat minder streng dan Git voor wat het in het auteur veld zet voor changesets, dus dit is een goed moment om schoon schip te maken.
Het aanmaken hiervan is een enkele commando regel in een bash
shell:
$ cd /tmp/hg-repo
$ hg log | grep user: | sort | uniq | sed 's/user: *//' > ../authors
Dit duurt een paar tellen, afhankelijk van de lengte van de geschiedenis van je project, en nadien ziet het /tmp/authors
bestand er ongeveer zo uit:
bob
bob@localhost
bob <bob@company.com>
bob jones <bob <AT> company <DOT> com>
Bob Jones <bob@company.com>
Joe Smith <joe@company.com>
In dit voorbeeld, heeft dezelfde persoon (Bob) changesets aangemaakt onder vier verschillende namen, waarvan er één er wel correct uitziet, en één ervan zou voor een Git commit helemaal niet geldig zijn.
Hg-fast-export laat ons dit corrigeren door elke regel in een instructie te veranderen: "<invoer>"="<uitvoer>"
, waarbij <invoer>
in een <uitvoer>
wordt gewijzigd.
Binnen de <invoer>
en <uitvoer>
tekenreeksen, worden alle 'escaped' reeksen die door de python string_escape
encoding worden begrepen ondersteund.
Als het auteur mapping-bestand geen passende <invoer>
regel heeft, wordt deze ongewijzigd doorgestuurd naar Git.
Als alle gebruikersnamen er goed uitzien, hebben we dit bestand helemaal niet nodig.
In ons voorbeeld, willen we dat ons bestand er zo uit ziet:
"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>"
Hetzelfde soort mapping bestand kan worden gebruikt om branches en tags te hernoemen als de Mercurial naam niet wordt toegestaan door Git.
De volgende stap is om onze nieuwe Git repository aan te maken en het volgende export script aan te roepen:
$ git init /tmp/converted
$ cd /tmp/converted
$ /tmp/fast-export/hg-fast-export.sh -r /tmp/hg-repo -A /tmp/authors
De -r
vlag vertelt hg-fast-export waar het de Mercurial repository kan vinden die we willen converteren, en de -A
vlag vertelt het waar het auteur-mapping bestand te vinden is.
Het script verwerkt Mercurial changesets en converteert ze in een script voor de "fast-import" functie (die we iets later zullen bespreken).
Dit duurt even (al is het veel sneller dan het via het netwerk zou zijn), en de uitvoer is nogal breedsprakig:
$ /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
Meer valt er eigenlijk niet over te vertellen. Alle Mercurial tags zijn geconverteerd naar Git tags, en Mercurial branches en boekleggers (bookmarks) zijn geconverteerd naar Git branches. Nu ben je klaar om de repository naar zijn nieuwe server-thuis te sturen:
$ git remote add origin git@my-git-server:myrepository.git
$ git push origin --all