Als je de vorige paragraaf leest over het gebruik van`git svn`, kan je eenvoudigweg deze instructies gebruiken om met git svn clone
een repository te maken en daarna te stoppen met de Subversion server, naar een nieuwe Git server te pushen en die beginnen te gebruiken.
Als je de historie wilt, kan je dat zo snel voor elkaar krijgen als je de gegevens uit de Subversion server kunt krijgen (en dat kan even duren).
Deze import is echter niet perfect, en omdat het zo lang duurt, kan je eigenlijk ook meteen maar goed doen.
Het eerste probleem is de auteur-informatie.
In Subversion, heeft elke persoon die commit heeft gedaan een gebruikersnaam op het systeem die wordt opgenomen in de commit-informatie.
De voorbeelden in de vorige paragraaf tonen schacon
in bepaalde plaatsen, zoals de blame
uitvoer en de git svn log
.
Als je dit beter op Git auteur-gegevens wilt mappen, moet je een relatie leggen van de Subversion gebruikers naar de Git auteurs.
Maak een bestand genaamd users.txt
die deze mapping-informatie heeft in een formaat als deze:
schacon = Scott Chacon <[email protected]>
selse = Someo Nelse <[email protected]>
Om een lijst van auteur-namen te krijgen die SVN gebruikt, kan je dit aanroepen:
$ svn log --xml --quiet | grep author | sort -u | \
perl -pe 's/.*>(.*?)<.*/$1 = /'
Dat maakt de loguitvoer in XML formaat aan, en behoudt vervolgens alleen de regels met auteur-informatie, verwijdert duplicaten en haalt de XML tags weg.
(Dit werkt duidelijk alleen op een machine met grep
, sort
, en perl
erop geïnstalleerd).
Stuur daarna de uitvoer naar je users.txt bestand zodat je de overeenkomstige Git gebruiker gegevens naast elke regel kunt zetten.
Je kunt dit bestand aan git svn
geven om het te helpen de auteur gegevens beter te mappen.
Je kunt git svn
ook vertellen de meta-data die Subversion normaalgesproken importeert niet mee te nemen, door --no-metadata
mee te geven aan de clone
of init
commando’s.
Hierdoor ziet je import
commando er ongeveer zo uit:
$ git svn clone http://my-project.googlecode.com/svn/ \
--authors-file=users.txt --no-metadata --prefix "" -s my_project
$ cd my_project
Nu zou je een mooiere Subversion import moeten hebben in je my_project
directory.
In plaats van commits die er uit zien als dit
commit 37efa680e8473b615de980fa935944215428a35a
Author: schacon <schacon@4c93b258-373f-11de-be05-5f7a86268029>
Date: Sun May 3 00:12:22 2009 +0000
fixed install - go to trunk
git-svn-id: https://my-project.googlecode.com/svn/trunk@94 4c93b258-373f-11de-
be05-5f7a86268029
zien ze er zo uit:
commit 03a8785f44c8ea5cdb0e8834b7c8e6c469be2ff2
Author: Scott Chacon <[email protected]>
Date: Sun May 3 00:12:22 2009 +0000
fixed install - go to trunk
Niet alleen ziet het Author veld er veel beter uit, maar de git-svn-id
is er ook niet meer.
Je moet ook nog wat opschonen na de import.
Onder andere moet je de vreemde referenties opschonen die git svn
heeft gemaakt.
Allereerst ga je de tags verplaatsen zodat ze echte tags zijn, in plaats van vreemde remote branches, en daarna verplaats je de overige branches zodat ze lokaal zijn.
Om de tags te verplaatsen zodat ze echte Git tags worden, roep je dit aan
$ for t in $(git for-each-ref --format='%(refname:short)' refs/remotes/tags); do git tag ${t/tags\//} $t && git branch -D -r $t; done
Dit neemt de referenties die remote branches waren en begonnen met refs/remotes/tags/
en maakt er echte (lichtgewicht) tags van.
Daarna verplaatsen we de overige referenties onder refs/remotes
om er lokale branches van te maken:
$ for b in $(git for-each-ref --format='%(refname:short)' refs/remotes); do git branch $b refs/remotes/$b && git branch -D -r $b; done
Het kan gebeuren dat je een aantal extra branches ziet die vooraf worden gegaan door @xxx
(waar xxx een getal is), terwijl je in Subversion aleen maar een branch ziet.
Dit is eigenlijk een Subversion kenmerk genaamd `peg-revisions'', wat iets is waar Git gewoonweg geen syntactische tegenhanger voor heeft.
Vandaar dat `git svn
eenvoudigweg het svn versienummer aan de branchnaam toevoegt op dezelfde manier als jij dit zou hebben gedaan in svn om het peg-revisie van die branch te adresseren.
Als je niet meer om de peg-revisies geeft, kan je ze simpelweg verwijderen:
$ for p in $(git for-each-ref --format='%(refname:short)' | grep @); do git branch -D $p; done
Nu zijn alle oude branches echte Git branches en alle oude tags echte Git tags.
Er is nog een laatste ding om op te schonen:
Helaas maakt git svn
een extra branch aan met de naam trunk
, wat overeenkomt met de standaard branch in Subversion, maar de trunk
-referentie wijst naar dezelfde plek als master
.
Omdat master
idiomatisch meer Git is, is hier de manier om die extra branch te verwijderen:
$ git branch -d trunk
Het laatste om te doen is om je nieuwe Git server als een remote toe te voegen en er naar te pushen. Hier is een voorbeeld van een server als een remote toe te voegen:
$ git remote add origin git@my-git-server:myrepository.git
Omdat al je branches en tags ernaar wilt sturen, kan je nu dit aanroepen:
$ git push origin --all
$ git push origin --tags
Al je branches en tags zouden nu op je nieuwe Git server moeten staan in een mooie, schone import.