Von Subversion zu Git migrieren

Der Wechsel von Subversion zu Git für die Versionsverwaltung ist an sich ein einfacher Vorgang. Da das Web aber voller veralteter Anleitungen ist steht man bald einmal in einer Sackgasse. Nachdem es mir auch so ergangen ist habe ich hier meine Lösungsansätze für Git 1.7.9.5 zusammengetragen.

 

History: Übernehmen oder verwerfen?

Die wohl wichtigste Frage bei der Migration dreht sich um die Änderungsgeschichte. Soll jeder einzelne je gemachter Commit übernommen werden? Oder will man nur einen bestimmten Stand migrieren? Bei beiden Ansätzen lassen sich Argumente dafür und dagegen finden. Wichtig ist das man diese Entscheidung überlegt trifft, da ein nachträgliche Änderung mit viel Arbeit verbunden ist.

 

Variante ohne History

Kann man auf die History verzichten ist die Migration sehr einfach. Es genügt den aktuellen Stand im SVN-Repository zu exportieren und damit ein Git-Repository zu initialisieren. Dies kann man sowohl mit grafischen Tools wie TortoiseSVN und GitHub for Windows machen wie auch direkt über die Kommandozeile.

svn export svn+ssh://user@localhost/svn/jgraber
cd jgraber
git init
git add .
git commit -m "init migrated repo"

 

Variante mit History

Wenn die History erhalten bleiben soll hilft git svn. Dies wird bei GitHub for Windows mitgeliefert und ist unter Linux über apt-get installierbar. Als Vorarbeit benötigen wir einen Checkout aus Subversion:

svn co svn+ssh://user@localhost/svn/jgraber
cd jgraber
svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors-transform.txt
cat authors-transform.txt
jgr = Johnny Graber <dev@JGraber.ch>

Zeile 3 erstellt eine Liste mit allen Personen die jemals in dieses Subversion Repository eingecheckt haben. Diese Liste benötigt man um die Usernamen von Subversion in die von Git her bekannten Autoren (im Format Vorname Nachname ) umzuwandeln. Sobald die Datei authors-transform.txt korrekt ausgefüllt ist geht es weiter mit der Migration:

git svn clone svn+ssh://user@localhost/svn/jgraber --no-metadata -A authors-transform.txt --stdlayout ../git_jgraber
cd ../git_jgraber

Dieser Befehl funktioniert nur wenn das Repository dem Standard mit den Verzeichnissen /trunk, /branches und /tags folgt. Hat man einen anderen Aufbau gewählt beendet sich git svn ohne Fehlermeldung. Die Lösung für dieses Problem ist das Weglassen der Option „--stdlayout„.

Branches übernehmen
Durch die bisherigen Aktionen wurde nur der Trunk von SVN in den Master bei Git überführt. Falls man unter SVN Branches verwendete müssen diese nun explizit übernommen werden. Dazu holt man sich erst eine Übersicht über alle Branches und übernimmt diese dann einzeln:

$ git branch -av
  1.0              2ef18cb Release 1.0 bugfixes
* master           e64eda5 litte changes on trunk
  remotes/1.0      2ef18cb Release 1.0 bugfixes
  remotes/tags/1.0 8604640 Release 1.0
  remotes/tags/1.1 9059098 bugfixed version 1.1
  remotes/trunk    e64eda5 litte changes on trunk
git checkout -b <local_branch> remotes/<remote_branch>
git branch -d -r <remote_branch>

Der letzte Befehl entfernt den Verweis auf den ursprünglichen Branch in SVN. Will man nicht mehr zurücksynchronisieren hat der Remote-Branch seinen Zweck erfüllt und kann entfernt werden.

Tags übernehmen
Wie die Branches müssen auch die Tags übernommen werden. Da SVN einem nicht zwingt Tags nur für einzelne Markierungen zu nutzen sollte man erst prüfen ob nicht ein Tag als Branch verwendet wurde. Ist dies der Fall migriert man diesen Tag wie einen Branch.

Sobald man nur noch „richtige“ Tags hat kann man diese Befehle für eine Übernahme nutzen:

$ git branch -av
  1.0              2ef18cb Release 1.0 bugfixes
* master           e64eda5 litte changes on trunk
  remotes/tags/1.0 8604640 Release 1.0
  remotes/tags/1.1 9059098 bugfixed version 1.1
git tag <local_tag> remotes/tags/<remote_tag>
git branch -d -r <remote_tag>

$ git tag
t1.0
t1.1

 

Ab zu GitHub

Als letzten optionalen Schritt kann man das migrierte Repository zu GitHub oder Bitbucket hochladen. Dazu legt man über die Weboberfläche des jeweiligen Anbieters ein neues Repository an. Die URL zu diesem Repository kann man nun dem lokalen hinzufügen und die Daten hochladen:

git remote add origin ssh://git@bitbucket.org/jgraber/
git push -u origin master
git push --tags
git push origin <branch>

 

Fazit

Ein Repository von Subversion nach Git zu migrieren ist gar nicht so schwer. Alles was man dazu braucht ist eine aktuelle Anleitung und eine Arbeitskopie die man auch einmal löschen kann. Sollte jemand einen einfacheren Weg für die Migration kennen würde ich mich über einen Kommentar freuen.