Posts Tagged ‘Git’

SVN-Repos auf eigenen Git Server migrieren

Sonntag, Juni 24th, 2012

Vor einer Weile hatte hatte ich mir einen SVN Server mittels WAMP zusammengebastelt. Die Lösung läuft bei mir aktuell immer noch, obwohl ich schon seit einer Weile auf lokale GIT Repositories gewechselt bin. Das hat es mir ermöglicht, jederzeit und unterwegs mit dem Repository zu arbeiten, also Verlauf einsehen und Änderungen einchecken, und sobald ich wieder netzwerktechnisch auf mein SVN zugreifen konnte, wurden die durchgeführten Commits einfach ins SVN übertragen. Den SVN-Server durch einen GIT “Server” zu ersetzen, war mir bisher zu aufwendig.

Die Tage bin ich dann über gitblit gestolpert. Dabei handelt es sich um ein Tool, in dem man einfach seine GIT Repositories hosten und auch für andere zugänglich machen kann. Das ganze kommt mit einem übersichtlichen Webfrontend daher, kurz gesagt: scheinbar ein perfekter Ersatz für meinen SVN Server.

Installation

gitblit gibt es in verschiedenen Download-Varianten. Die “GO” Variant beinhaltet alles was man braucht um direkt loszulegen, kommt dabei “aber” mit einem eigenen Jetty Webserver daher. Da ich eher einen lokalen Tomcat verwenden möchte, habe ich mir einfach die WAR-Datei (Web Archive) heruntergeladen.

Der Tomcat liegt bei mir unter D:\temp\apache-tomcat-7.0.28, d.h. die WAR-Datei wird in das Unterverzeichnis “webapps\gitblit” entpackt. Änderungen an den Einstellungen habe ich für meinen Test keine vorgenommen. Die vollständige Einrichtung erledige ich wenn ich genug getestet habe. Zum Abschluss sollte man prüfen, ob der Tomcat auch gestartet ist.

Tja, das war es eigentlich auch schon. Wenn man jetzt im Webbrowser die Adresse http://localhost:8080/gitblit/ aufruft, bekommt man folgende Seite zu Gesicht.

Erste Schritte

Für die Verwaltung der Repositories muss man sich anmelden. Einfach oben rechts mit Benutzer admin und Passwort admin anmelden. Jetzt bekommt man zusätzliche Navigationspunkte und Funktionen angezeigt.

Etwa rechts in der Mitte (also oberhalb der leeren Repository-Liste) hat man die Möglichkeit ein neues Repository anzulegen. Mit einem Klick auf “new repository” gelangt man zu einer Seite mit vielen Einstellungen. Ich gebe nur ins erste Feld den Name “test” ein und klicke ganz unten auf “Save”. Damit habe ich ein neues Repository angelegt und das wird jetzt in der Übersicht als leer angezeigt. Jetzt muss man seinem lokalen Git-Repository nur noch den neuen Remote-Server mitteilen, und schon kann man mittels Push das Repo auf den Server übertragen. Die notwendigen Schritte/Befehle werden direkt im gitblit-Frontend angezeigt. Einfacher geht es nicht.

SVN Migration

Als nächstes möchte ich eines meiner SVN-Repositories in das eben erstellte importieren. Das gestaltet sich nicht ganz so einfach, da man mehrere Dinge beachten sollte:

  1. Man benötigt ein Author-Mapping, damit die Namen aus dem SVN-Repository nicht verloren gehen
  2. Alle SVN-Branches müssen in Git als Branch angelegt werden
  3. Alle SVN-Tags müssen in Git angelegt werden

Zum Glück muss ich mir nicht alles selbst zusammensuchen und kann auf Hilfe auf dem Internet zugreifen. Sämtliche nun folgenden Arbeiten führe ich in der “Git Bash” aus, die man ja eigentlich intstalliert hat, wenn man mit Git unter Windows arbeitet. Wenn nicht, dann msysGit installieren.

Author Mapping

Um überhaupt an die eine Liste der Authoren heranzukommen, greift man am Besten auf ein kleines Bash-Script zurück. Das in Sven’s Blog bereitgestellte Skript, musste ich leicht anpassen, da es a) mit Leerzeichen in Authoren nicht klar kam und b) ein lokales SVN-Repository benötigte. An die geänderte Version kann ich einfach eine URL zum SVN-Server übergeben und schon bekomme ich eine Liste der Authoren. Hier das geänderte Script “svn_author_export.sh” (Download weiter unten):

#!/bin/bash
IFS=$(echo -en "\n\b")
authors=$(svn log -q $1 | grep -e '^r' | awk 'BEGIN { FS = "|" } ; { print $2 }' | sort | uniq)
for author in ${authors}; do
  echo "${author} = ${author} <${author}@domain.com>" >> svn.authors ;
done

Der Aufruf sieht dann wie folgt aus:

./svn_author_export.sh http://localhost/svn/svnGitTest

Im lokalen Verzeichnis gibt es nach dem Ausführen eine Datei namens “svn.authors”, die man jetzt entsprechend anpassen sollte.

SVN Repository clonen

Das eben erstellte Author-Mapping kommt beim Clonen des SVN-Repositories zum Einsatz.

git svn --authors-file=./svn.authors clone -s http://localhost/svn/svnGitTest

Jetzt hat man ein lokales Git-Repository mit sämtlichen Commits aus dem SVN und den entsprechend gemappten Author-Namen/Emailadressen. Das kann man durch einen Blick ins “git log” überprüfen.

Repository migrieren

Nachdem man das SVN-Repository nach Git geclont hat, sind einige Aufräumarbeiten notwendig. So muss man für jede SVN-Branch auch eine lokale Git-Branch erstellen, und auch die Tags aus dem SVN korrekt übernehmen. Um diesen Schritt zu automatisieren habe ich ein kleines Script gebastelt (Download weiter unten):

#!/bin/bash
branches=$(git branch -a | grep -e ' remotes/' | awk -F: '{print substr($0, 3)}')
for branch in ${branches}; do
  tagName=$(expr "$branch" : "remotes/tags/\(.*\)")
  branchName=$(expr "$branch" : "remotes/\(.*\)")
  if [ -n "$tagName" ]; then
    git checkout -b tag_"$tagName" remotes/tags/$tagName
    git tag $tagName tag_"$tagName"
    git checkout master
    git branch -D tag_"$tagName"
    git branch -D -r tags/$tagName
  else 
    if [ "$branchName" != "trunk" ]; then
      git checkout -b $branchName remotes/$branchName
    fi
    git checkout master
    git branch -D -r $branchName
  fi
done

Ok, was passiert in diesem Script?

  1. Zunächst werden alle Remote-Branches ermittelt
  2. Dann wird unterschieden, ob es sich um einen Tag oder eine echte Branch handelt
  3. Bei Tags wird temporär eine Branch (basierend auf dem Remote-Tag) angelegt und darauf ein entsprechender Tag erzeugt.
  4. Bei Branches wird einfach eine entsprechende Branch angelegt (außer für die Remote-Branch “remotes/trunk”)
  5. … und nebenbei werden alle Remote-Branches gelöscht, also das Repository vom SVN abgekoppelt.

Jetzt sollte man genau prüfen, ob irgendwelche Fehler aufgetreten sind. Falls etwas schief gegangen ist, hilft es meist nur,  das gesamte Repository frisch aus dem SVN zu clonen (oder man hat sich vorher ein Backup vom Verzeichnis gemacht). Ggf. sollte man den 5ten Schritt weglassen, wenn man sein SVN- und den Git-Server parallel laufen und Commits zwischen beiden syncronisieren lassen möchte.

Auf den Server übertragen

Nun ist es an der Zeit unser Repository auf den Server zu übertragen. Dazu müssen wir unserem lokalen Git-Repository erstmal ein neues Remote mitteilen und dann unsere Branches und Tags pushen.

git remote add gitblit http://localhost:8080/gitblit/git/svnGitTest.git
git push gitblit master work_test work_new work_experimental first_tag

Das kann natürlich wieder aufwändig werden, wenn man sehr viele Branches/Tags hat. Dafür kann man aber auch ein kleines Script (commit_all_branches_and_tags.sh) benutzen.

Wie man sieht, ermittelt das Script selbstständig alle Branches und Tags und puscht diese an das Remote mit dem Namen “gitblit”. Wenn ein anderer Name für den Remote verwendet wurde, dann kann man den Namen einfach als ersten Parameter an das Script übergeben. Hier noch das Script (Download weiter unten):

#!/bin/bash
remote="gitblit"
if [ -n "$1" ]; then
  remote=$1
fi
branches=$(git branch | awk -F: '{print substr($0, 3)}')
tags=$(git tag)
entries="${branches} ${tags}"
entries=${entries[*]}
echo "Committing: ${entries}" 
git push ${remote} ${entries}

Jetzt kann man sich auch das Ergebnis im Webfrontend anschauen oder sich das Repository auf einen anderen Rechner clonen.

Zusammenfassung

Auch wenn das Migrieren im ersten Moment doch etwas aufwändig erscheint, kann man mit wenigen Handgriffen oder durch die Verwendung von Scripts recht schnell zum Ziel gelangen. Grad der in die Scripte gesteckte Aufwand wird sich bei der Migration der weiteren Repositories auszahlen. Ob man bei der Migration gitblit oder eine andere Lösung aufbaut — in beiden Fällen kann ich hier wieder auf die Scripte und Vorgehensweise zurückgreifen.

Eine kleine Änderung an der Konfiguration von gitblit musste ich dann doch vornehmen. Bei Branches und Tags wurde im Webfrontend nur eine leere Seite angezeigt. Das Problem ist aber bekannt und kann (in des Dateien reference.properties und web.xml) durch das Setzen von “web.mountParameters” auf “false” beseitigt werden.

Die restlichen Funktionen von gitblit muss ich jetzt nach und nach ausprobieren. Aber mein SVN-Server wird wohl bald ausgediehnt haben.

Links
Gitblit-Homepage
SVN to Git Migration von Sven Goethel
Download der Scripte