senäh

17senäh und so…

Allgemein
10. Sep 2012
Kommentare: 0

SVN-Prinzipien an Beispielen erklärt

Kategorien: Allgemein | 10. Sep 2012 | Kommentare: 0

Serie: Versionskontrolle for the rest of us

Dieser Teil der Serie soll den trockenen Prinzipien aus dem Vorherigen durch konkrete Beispiele ein bisschen Leben einhauchen. Aus dem letzten Artikel habt ihr hoffentlich mitgenommen, dass die Versionsverwaltung mit SVN im Wesentlichen aus 3 Vorgängen besteht:

  • Checkout (Daten initial aus dem Repository holen),
  • Update (Änderungen anderer Entwickler aus dem Repository holen) und
  • Commit (eigene Änderungen an das Repository schicken).

SVN-Clients

Diese Operationen lassen sich alle über die Kommandozeile bewerkstelligen, ich greife jedoch stets auf Clients für diese Aufgabe zurück. Unter Windows war dies stets Tortoise SVN. Ein Programm, das bei verdächtigen Dateien SVN-Operationen im Kontextmenü über einen Rechtsklick bereitstellt. Funktioniert gut und ist kostenlos.

Auf dem Mac verwende ich Cornerstone. Es gibt auch kostenlose Alternativen wie SmartSVN und SourceTree, allerdings gefiel mir Cornerstone so gut, dass ich bereit war das Geld dafür auszugeben. Ich habe bereits auf meinem Mac-Blog einen Beitrag zu Cornerstone hinterlassen, falls ihr euch einen Eindruck verschaffen wollt. Andernfalls kann ich euch nur die 14-Tage-Demo auf der Webseite ans Herz legen.

Daneben gibt es eine ganze Schaar weiterer GUI-Programme für SVN. Sucht euch ruhig ein bisschen durch das Internetz. Oder benutzt halt die Kommandozeile 🙂

Repository hinzufügen

Nehmen wir jetzt aber die angesprochenen Beispiele in Angriff. Operation Numero 1: der initiale Checkout. Dafür braucht ihr die Zugangsdaten zum Repository. Fragt dazu euren Vorgesetzten oder den Admin eurer Wahl 😉

In Cornerstone müsst ihr zunächst das Repository hinzufügen, um anschließend eine Working Copy auschecken zu können (die Anglizismen machen hier Sinn um sich an das Vokabular zu gewöhnen ;)). In manchen Clients sind diese beiden Schritte auch in einem gekapselt, da sie in der Regel direkt hintereinander erfolgen.

Hinzufügen eines Repositorys in Cornerstone

Hinzufügen eines Repositorys in Cornerstone

Wie ihr seht, benötigt ihr den Link zum Repository sowie die Zugangsdaten. Das Feld Nickname ist nur für eure Referenz, damit ihr euch später in eurer massiven Sammlung von Repositories zurecht findet. Die Bezeichnung trunk rührt von einer SVN-Konvention, nach der ein Repository immer 3 Ordner auf oberster Ebene beinhalten sollte:

  1. branch,
  2. tag und
  3. trunk.

Trunk

Letzterer stellt den aktuellen Hauptentwicklungszweig dar. Darum ist in vielen Fällen lediglich dieser von Interesse.

Branch

Für die Entwicklung spezieller Features ist es nicht unüblich einen extra Branch aufzumachen. Dadurch könnt ihr ein Feature isoliert implementieren, unabhängig vom aktuellen Entwicklungsstand. Am Ende werden alle Änderungen dann zusammen gemerget.

Tag

Tags sind im SVN-Jargon nichts anderes als spezielle Versionsnummern, also 1.0, 2.1 oder 17.8.3. Sinnvoll für spezielle Anfragen von Kunden, die eine bestimmte Version eurer Software verwenden. Habt ihr also einen Stand erreicht, den ihr released, macht es Sinn ein Tag dafür anzulegen.

Ich möchte hier nicht zu sehr ins Detail gehen, da es für den Anfang eventuell etwas viel ist. Außerdem hält sich meine Erfahrung damit in Grenzen, so dass ich durch das Auslassen weiterer Erläuterungen das Risiko verringere, Halbwissen zu vermitteln 🙂

Checkout

Einmal hinzugefügt könnt ihr aus dem Repository eine Working Copy auschecken, wodurch die Source-Files in ein Verzeichnis eurer Wahl kopiert werden. Außerdem werden die SVN-eigenen Daten ebenfalls kopiert. Diese erkennt ihr am Namen .svn. Es handelt sich hierbei um versteckte Dateien, die ihr erst sichtbar schalten müsst. Eigentlich habt ihr darin aber nichts verloren 😉

Der entsprechende Dialog in Cornerstone sieht so aus:

Checkout einer Working Copy in Cornerstone

Checkout einer Working Copy in Cornerstone

Revisionen

Kurz zum Punkt Revision: eine Revision bezeichnet einen einzelnen Entwicklungsschritt. Es handelt sich dabei um eine fortlaufende Nummer, die mit jedem Commit erhöht wird. Wenn ihr also euer Repository bei Revision 17 auscheckt und 3 Commits vornehmt, lautet die aktuelle Revisionsnummer 20. Diese wird auch als HEAD-Revision bezeichnet. Und wenn ihr jetzt zurück in den Screenshot schaut, könnt ihr hoffentlich nachvollziehen, warum dort Latest in Repository (HEAD) steht.

Und das war es auch schon zum Checkout-Vorgang. Weiter geht’s mit dem Commit-Vorgang.

Commit

Wie ihr oben vielleicht bemerkt habt, habe ich ein Repository namens Einkaufsliste ausgecheckt. Ich gebe zu, sonderlich realitätsnah ist das nicht. Allerdings wird es gut funktionieren, um die Vorgänge deutlich zu machen.

Die Arbeitskopie will also bearbeitet werden. Nehmen wir an, wir haben eine einfache einkaufsliste.txt mit folgendem Inhalt:

3l Milch
2 Tiefkühlpizzen
1 Kasten Club Mate

Jetzt stellen wir fest, dass 2 Tiefkühlpizzen für die Woche nicht genug sind, also packen wir noch 3 Tütensuppen dazu. Mal schauen, wie weit wir damit kommen.

3l Milch
2 Tiefkühlpizzen
3 Tütensuppen
1 Kasten Club Mate

Eine Änderung, die einen signifikanten Entwicklungsstand darstellt, weswegen wir sie direkt comitten. In Cornerstone stellt sich diese wie folgt dar:

Commit der Änderungen in Cornerstone

Commit der Änderungen in Cornerstone

Ich kann Dateien für den Commit über eine Checkbox an- und abwählen (in diesem Fall gibt es ja nur die Eine) und eine Nachricht hinzufügen (added instant soup to shopping list). Mit ⌘T oder über den Button unten rechts wird der Commit abgesendet und alle beteiligten Entwickler haben Zugriff auf die geänderte Einkaufsliste.

Update

Wie auch im letzten Teil schreite ich hier ein und sage: erst Update, dann Commit! Ich habe es hier der Einfachheit halber weggelassen.

Schauen wir uns zum Thema Update 2 Situationen genauer an. Numero Eins: einen normalen Update-Vorgang (später folgt dann ein Beispiel zu Konflikten).

Erweitern wir die Einkaufsliste ein bisschen. Akkus für Bluetooth-Tastaturen und -Mäuse wären praktisch. Also rauf damit.

3l Milch
2 Tiefkühlpizzen
3 Tütensuppen
1 Kasten Club Mate
neue Akkus

Bevor wir die Änderungen comitten, machen wir diesmal ein Update. Und siehe da, andere Entwickler haben zahlreiche Vorschläge hinterlassen. Die Änderungen werden aus dem Repository geholt und in eure Arbeitskopie gemergt.

3l Milch
2 Tiefkühlpizzen
1 Tischkicker
3 Tütensuppen
9 kg Dallmayr Prodomo
1 Kasten Club Mate
2 Retina MacBooks
neue Akkus

Konflikte

Schauen wir uns den interessanteren Fall an, wenn mal etwas schief geht. Folgende Situation: in einer Küchenpause habt ihr euch über den Kaffee unterhalten und entschieden, dass ihr 1. mehr und 2. anderen benötigt. Da ihr in einem besonders engagierten Team arbeitet, pflegen gleich 2 Entwickler auf einmal die Änderungen ein, sobald sie zurück am Schreibtisch sind. Einer davon seid ihr. Ihr ändert die Einkaufsliste folgendermaßen ab:

3l Milch
2 Tiefkühlpizzen
1 Tischkicker
3 Tütensuppen
17 kg äthiopischer Bio-Kaffee
1 Kasten Club Mate
2 Retina MacBooks
neue Akkus

Dann fahrt ihr ein Update und stellt fest, dass euer Kollege schneller war. Was entsteht ist ein – Pro–7-Blockbuster-Stimme – Merge Conflict. Die Datei sieht anschließend so aus.

3l Milch
2 Tiefkühlpizzen
1 Tischkicker
3 Tütensuppen
<<<<<<< .mine
17 kg äthiopischer Bio-Kaffee
=======
12 kg Cappucino-Pulver
>>>>>>> .r5
1 Kasten Club Mate
2 Retina MacBooks
neue Akkus

SVN markiert die kritischen Stellen, eure mit mine, die aus dem Repository mit der entsprechenden Revisionsnummer (hier die 5). Außerdem legt es dazu 3 Dateien an:

  • einkaufliste.txt.mine (eure Version)
  • einkaufliste.txt.r5 (Version im Repository)
  • einkaufliste.txt.r4 (Version vor dem Konflikt, ohne eure Änderungen und ohne die Änderungen eures Kollegen)

Diese sollen euch helfen, die Konflikte ggf. zu beseitigen bzw. die einen oder anderen Änderungen zu verwerfen. Entsprechend könnt ihr bei SVN-Clients auch auswählen, ob ihr zum Lösen des Konflikts:

  • eure Änderungen behalten wollt,
  • die Änderungen eures Kollegen übernehmt oder
  • die Original-Datei bearbeitet.

Letzteres ist dann sinnvoll, wenn es an mehreren Stellen kracht und ihr die Änderungen einzeln durchgeht und fixt.

Wichtig ist, dass ihr SVN mitteilt, dass ihr den Konflikt auch gelöst habt, sobald dies geschehen ist. Solange ihr dies nicht getan habt, könnt ihr keine Dateien mehr comitten, da SVN keine konfliktbehafteten Arbeitskopien duldet. In dem Moment, wo ihr den Konflikt als gelöst markiert, werden auch die 3 Extra-Dateien wieder gelöscht, so dass ihr eine saubere Arbeitskopie habt.

In meinem Fall würde ich – um die allgemeine Betriebsharmonie zu wahren – den Vorschlag meines Kollegen akzeptieren und den Konflikt auflösen, indem ich seine Variante als die Korrekte markiere. Mehr ist anschließend auch gar nicht zu tun. Ihr seht also, die vielgefürchteten Konflikte sind nervig, aber kein Hexenwerk.

Next up: Git

So, reicht mal wieder hin. Ich hoffe, dass euch SVN nun kein überdimensionaler Dorn mehr im Auge ist. Einmal dahinter gestiegen kann man für dieses clevere Tool tatsächlich ziemlich dankbar sein.

Im nächsten Teil werde ich Git aus der Sicht eines SVN-Umsteigers beleuchten. Freut euch darauf 🙂

Autor: Enno

Ich bin Enno. PHP ist mein Ding, aber auch alles Neue rund um die Themen HTML5, CSS3 & Co finde ich interessant. Ich mag es Leuten zu helfen und mein Wissen weiterzugeben. Sollte dir mein Beitrag gefallen haben, lass doch nen Kommentar da oder benutze einen der Social Buttons, um deinen Dank auszudrücken ;)