Aus verschiedenen Gruenden wollte ich unsere Subversion-Repositories nach Git migrieren. Die Entscheidung dafuer war unabhaengig davon, dass zwei Projekte, naemlich FAI und Serendipity, etwa zur gleichen Zeit migriert sind.
Git ist ein verteiltes Versionskontrollsystem (DVCS) - in der gleichen Liga spielen auch Bazaar und Mercurial, wobei das „verteilt“ nicht der Grund fuer den Wechsel war. Neben der komprimierten Speicherung und bandbreitenschonenden Uebertragung, spielen die neuen Systeme ihre Staerken vor allem im intelligenten Zusammenfuehren (merging) von unterschiedlichen Versionen aus.
Weitere Vorteile sind (die Liste ist nicht komplett):
Einen sehr guten Einstieg in verteilte Versionskontrollsysteme und insbesondere Git bietet die Ausgabe 130 von Chaosradio Express.
Subversion wurde bei uns ueber dav_svn
, ein Modul des Webservers, benutzt. Die Migration musste also in drei Schritten passieren, zuerst die Serverseite, um die Infrastruktur zur Verfügung zu stellen, danach die Migration der bestehenden Projekte und zum Schluss die Umstellung der Clients.
Da Taskwarrior Gitosis einsetzt und ich so immer jemanden habe, den ich fragen kann, habe ich mich fuer Gitosis auf der Serverseite entschieden. Dafuer gibt es bereits eine sehr gute Anleitung, die ich leider ziemlich unuebersichtlich finde, daher fuehre ich hier noch einmal die einzelnen Schritte auf. Unsere Server laufen auf Ubuntu 10.04 LTS und ich bin strikt nach Anleitung vorgegangen.
sudo aptitude install git-core gitosis
Erzeugt einen User „gitosis“ und die nötigen Verzeichnisse unter /srv/gitosis
Danach muss ich den eigenen oeffentlichen SSH-Schluessel auf den Server kopieren und damit das Administrations-Repository initialisieren (darin wird die ganze Konfiguration gemacht).
dirk@client$ scp .ssh/id_rsa.pub server:/tmp/dirk@client.pub dirk@server$ sudo -H -u gitosis gitosis-init < /tmp/dirk@client.pub
Damit ist die serverseitige Einrichtung bereits abgeschlossen. Unglaublich aber wahr.
Was nicht in der Anleitung steht, jetzt aber lokal erledigt werden sollte, da commits in Git immer Usernamen und E-Mail-Adresse enthalten:
git config --global user.name "John Doe" git config --global user.email "john@doe.com" git config --global color.ui always
Der letzte Befehl ist nicht wichtig, der macht es nur huebsch.
Jetzt kann das gerade angelegte Adminrepository ausgechecked werden:
git clone gitosis@server:gitosis-admin.git gitosis-admin-server.git
Das letzte in der Kommandozeile ist der Name, wie das Verzeichnis lokal heissen soll. Ich habe ein „-server.git“ hinzugefügt, da das Verzeichnis sonst nur „gitosis-admin“ geheissen haette.
Jetzt können der Admingruppe weitere User hinzugefügt werden.
In gitosis.conf
stand am Anfang nur dirk@client
:
[group gitosis-admin] writable = gitosis-admin members = dirk@client dirk@workstation
Im Verzeichnis keydir
sind die ganzen Schluessel zu finden. dirk@client.pub
war schon vorher enthalten.
ls -l keydir/ total 12 -rw-r--r-- 1 dirk dirk 393 Nov 4 10:50 dirk@client.pub -rw-r--r-- 1 dirk dirk 395 Nov 4 10:54 dirk@workstation.pub
Die Aenderungen werden jetzt an den Server uebertragen.
git add keydir/dirk@workstation.pub git commit -a -m "User dirk@workstation hinzugefuegt" git push
Git verhaelt sich ein bisschen anders als Subversion.
Ein neues Repository auf dem Server legt man wie folgt an. Zuerst traegt man es in die gitosis.conf ein.
[group playground] writable = playground members = dirk@client dirk@workstation
Danach uebertraegt man die neue Konfiguration auf den Server.
$ git commit -a -m "playground erzeugt" [master 8a62406] playground erzeugt 1 files changed, 4 insertions(+), 0 deletions(-) $ git push Counting objects: 5, done. Delta compression using up to 4 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 375 bytes, done. Total 3 (delta 0), reused 0 (delta 0) To gitosis@foo:gitosis-admin.git 4755284..8a62406 master -> master
Wir initialisieren das Repositories (ebenfalls lokal):
$ git clone gitosis@server:playground.git playground-server.git Cloning into playground-server.git... Initialized empty Git repository in /srv/gitosis/repositories/playground.git/ warning: You appear to have cloned an empty repository. $ cd playground-foo.git/ $ touch foo $ git add . $ git commit -m "init" [master (root-commit) 8b70e1d] init 0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 server $ git push origin master Counting objects: 3, done. Writing objects: 100% (3/3), 197 bytes, done. Total 3 (delta 0), reused 0 (delta 0) To gitosis@server:playground.git * [new branch] master -> master
Nachdem das alles funktioniert, koennen die Subversion-Repositories migriert werden, Anleitung dazu im freien Buch Pro Git.
Subversion nutzt Usernamen um die Commits zu kennzeichnen, Git nutzt reale Namen und E-Mail-Adressen, damit ist der erste Schritt klar, wir brauchen eine Liste der User, die schon in unser Repository geschrieben haben und muessen diese mit Realnamen abgleichen.
$ svn log --xml | grep author | sort -u | perl -pe 's/.>(.?)<./$1 = /'
Mit dem obigen Befehl bekommt man alle Committer aus einem Subversion-Repository, damit laesst sich eine Datei users.txt
aufbauen, in der die Usernamen und die Git-Namen zu finden sind. Ich habe das auch zur Konsolidierrung benutzt.
dirk = Dirk Deimeke <dirk@deimeke.net> lux = Dirk Deimeke <dirk@deimeke.net> user = Vorname Nachname <name@example.com>
Mit dieser Vorarbeit ist es bereits moeglich, das Subversion-Repository zu klonen und zu konvertieren (ACHTUNG: Unterschied zum Buch, bei mir hat die Option -s
nicht funktioniert, da ich kein Standard-Layout verwendet habe und statt git-svn
habe ich git svn
benutzt).
$ git svn clone http://my-project.googlecode.com/svn/ \ --authors-file=users.txt --no-metadata my_project
Jetzt gilt es noch, Aufraeumarbeiten durchzufuehren. Zuerst machen wir aus den Tags von Subversion Git Tags.
$ cp -Rf .git/refs/remotes/tags/* .git/refs/tags/ $ rm -Rf .git/refs/remotes/tags
Als naechstes machen wir aus den remote Referenzen lokale Branches:
$ cp -Rf .git/refs/remotes/* .git/refs/heads/ $ rm -Rf .git/refs/remotes
So, jetzt muessen wir das ganze noch hochladen.
$ git remote add origin git@my-git-server:myrepository.git
Und, weil wir alles uebertragen wollen, geht es mit dem folgenden Kommando los:
$ git push origin --all
Fertig!
Ich hatte bei der Migration mit einem groesseren Problem zu kaempfen. Mein privates Repository hat ueber 2000 commits und einige Gigabytes an Daten. Das hat meinen lokalen Rechner in die Knie gezwungen, da waren 4 GB Speicher zu knapp. Ich habe die Migration kurzerhand auf einem Server mit 8 GB RAM laufen lassen, das ging. Alternativ dazu kann man aber mit git-svn
die Migration haeppchenweise durchfuehren. Mit git svn clone -r0:100
(und den anderen Optionen weiter oben) werden nur die ersten 100 Commits geklont, dann macht man mit -r100:200
weiter bis man letztendlich fertig ist.
Es gibt einen sehr guten Git - SVN Crash Course, daher fuehre ich hier nur die Unterschiede der haeufigsten Kommandos an.