Versionskontrolle mit Git
Linus Torvalds war unzufrieden. Denn keines der 2005 verfügbaren Versionskontrollsysteme (Version Control System, VCS) erfüllte seine Ansprüche. Nachdem das proprietäre „BitKeeper“ aufgrund einer Lizenzänderung nicht mehr für die Verwaltung des Linux-Kernels verwendet werden konnte, musste eine Alternative her. Allerdings sollte sie dezentral, skalierbar, einfach aufgebaut und – vor allem – schnell sein.
Die Linux-Community handelte: Mit Git [1] und Mercurial entstanden aus dieser Not heraus gleich zwei Lösungen, die heute für das Beste stehen, was dezentrale Versionskontrollsysteme zu bieten haben. Dafür sprechen auch die Referenzen. So wird Git aktuell für den Linux-Kernel, TYPO3, Symfony, Cake PHP, jQuery, Ruby on Rails, Debian, Fedora, Perl und viele andere Open-Source-Projekte eingesetzt.
Zentral vs. Dezentral
Klassische Versionsverwaltungen wie Subversion oder CVS arbeiten „zentralisiert“ (CVCS). In diesen Systemen gibt es nur ein einziges Master-Repository, in das alle Entwickler ihre Änderungen einspeisen, jede Aktion muss mit diesem zentralen Repository abgestimmt werden. Da dieser Master meist auf einem zentralen Server liegt, bedeutet das auch, dass jede Aktion über das Netzwerk wandern muss und ein Entwickler mehr oder weniger „arbeitsunfähig“ ist, wenn er gerade einmal keine Netzwerkverbindung hat.
Git ist (wie auch Mercurial) ein „dezentrales“ oder „distributed“ VCS (DVCS). In dezentralen Systemen hat jeder Entwickler ein eigenes, vollwertiges Repository auf seinem Computer. Zusätzlich existiert in den meisten Fällen noch ein zentrales Repository auf einem Server, das zum Austausch genutzt werden kann. Dies ist aber keine Bedingung – jeder Entwickler kann alle wichtigen Aktionen lokal auf seinem Repository ausführen.
Dabei spielt es keine Rolle, ob man ein komplexes System mit mehreren entfernten Repositories aufbaut, oder ganz einfach „klassisch“ einen einzigen zentralen Server zum Austausch nutzt. Das lokale Arbeiten bei dezentralen Versionsverwaltungen bietet in beiden Fällen zwei große Vorteile gegenüber klassischen Systemen: Einerseits sind Entwickler nicht an das Internet und den Server gebunden; sie können vielmehr entwickeln, wann und wo sie wollen. Andererseits dienen sich die lokalen Repositories als vollwertige Backups an. Immerhin speichern sie, wie auch die zentralen Repositories, die komplette Historie aller Dateien.
Strukturen
Git verwaltet Projekte in einem zentralen Ordner („.git“), der im Root-Verzeichnis des jeweiligen Projekts liegt. Im Gegensatz zu Subversion sind sämtliche Unterverzeichnisse – das sogenannte „Working Directory“ (bzw. der „Working Tree“) – somit frei von Projektdateien, die beim Löschen oder Verschieben von Ordnern verloren gehen könnten.
Ein wichtiger Bestandteil im täglichen Git-Umgang ist die „Staging Area“. Durch sie können einzelne Änderungen in den nächsten Commit aufgenommen oder von selbigem ausgeschlossen werden, und das bis auf einzelne Zeilen einer Datei genau. Somit lassen sich etwa Änderungen zu thematisch einheitlichen Commits verbinden oder auf später verschieben. Technisch gesehen ist die Staging Area lediglich eine Datei namens „index“, die im .git-Verzeichnis liegt – daher auch manchmal die synonyme Bezeichnung „index“.
Zustände
Git kennt mehrere Zustände, in denen sich Dateien der Working Directory befinden können. Grundsätzlich unterscheidet das System zwischen „tracked“ und „untracked“. Eine Datei gilt als tracked, wenn sie bereits unter Versionskontrolle ist, sie also in einem Commit enthalten war. Untracked ist eine Datei, die (noch) nicht im Git-Repository gespeichert ist.
Spannend für die weitere Betrachtung sind daher insbesondere Dateien im tracked-Zustand, denn nur Veränderungen an diesen werden von Git beobachtet. Eine tracked-Datei kann wiederum einen von drei Zuständen annehmen:
- unmodified/committed: Die Datei wurde lediglich commited, enthält also keine neuen, lokalen Änderungen.
- modified: Die Datei wurde seit dem letzten Commit verändert.
- staged: Die Datei wurde nicht nur verändert, sondern die Änderungen wurden auch der Staging Area hinzugefügt, also für den nächsten Commit markiert. Da auch nur Teile (beispielsweise einzelne Zeilen) einer Datei markiert sein können, kann eine Datei teilweise staged und modified sein.
Workflow
Dank Installer und Paketmanager ist Git einfach und schnell eingerichtet. Im kostenlos verfügbaren E-Book „Pro Git“ [2] werden außerdem die notwendigen Schritte für die verschiedenen Plattformen erklärt.
Bedient wird Git klassischerweise von der Kommandozeile aus. Für viele
Anwendungsfälle macht allerdings ein entsprechender Desktop-Client (beispielsweise „Tower“ für Mac OS [3] oder „Tortoise Git“ für Windows [4] ) das Leben leichter.
Nach dem Erstellen, Löschen oder Ändern von Dateien im Working Directory listet Git den aktuellen Status mit dem Befehl „git status“ auf der Kommandozeile auf. Um Änderungen in den nächsten Commit aufzunehmen, müssen sie mittels „git add“ der Staging Area hinzugefügt werden. Schließlich speichert ein „git commit“ unter Angabe einer Commit-Nachricht die Änderungen im lokalen Repository.
Um mit anderen Entwicklern an ein und demselben Projekt arbeiten zu können, werden „Remote Repositories“ (kurz „Remote“) gebraucht. Die zentral im Internet oder lokalen Netzwerk abgelegten Repositories funktionieren genau wie die lokalen Installationen. Einzig ein Working Directory fehlt, da ein Remote nur Austausch-Medium und keine aktive Arbeitsumgebung ist.
Git ist außerdem imstande, für jedes lokale Repository beliebig viele Remotes zu verwalten. Das ermöglicht es, Code selektiv mit unterschiedlichen Parteien zu teilen.
Revisions-Hash
Git kennt keine Revisionsnummern. Während in zentralisierten VCS wie Subversion jeder Commit eine fortlaufende Revisionsnummer erhält, funktioniert dies in dezentralen Systemen nicht. Da die Commits lokal entstehen, kann Git keine finale Reihenfolge voraussehen, wenn die Commits später auf einem Remote veröffentlicht werden.
Stattdessen verwendet Git SHA-1-Hashes, 40 Zeichen lange Prüfsummen, zur Identifizierung von Commits (und intern auch aller anderen Objekte). Sie sind genauso eindeutig wie Revisionsnummern, aber aufgrund ihrer Zufälligkeit nicht aufsteigend und damit auch in dezentralen Systemen einsetzbar.
Fortsetzung folgt
In der nächsten t3n-Ausgabe 25 liegt der Fokus noch stärker auf dem täglichen Umgang mit Git. Der Folgeartikel erklärt neben einem Workflow aus der Praxis auch, in welchen Bereichen Git seine Stärken optimal ausspielen kann.