Git erobert die Entwicklerwelt

Git für Einsteiger: Wie man das Versionskontrollsystem Git nutzt

Git für Einsteiger: Wie man das Versionskontrollsystem Git nutzt

Git erobert die Entwicklerwelt

Git für Einsteiger: Wie man das Versionskontrollsystem Git nutzt


Git ist „hip“ und gilt als Star unter den Versionskontrollsystemen. Der Grund dafür ist einfach: Git ist schnell, leistungsfähig und plattformunabhängig. Kein Wunder, dass immer mehr Teams vor allem auch aus der Microsoft-Welt den Umstieg planen. Doch um Git optimal zu nutzen, ist fundiertes Hintergrundwissen nötig – denn Git arbeitet von Grund auf anders als die bekannten „klassischen“ Systeme. Richtig eingesetzt macht Git aber ordentlich Spaß – durch mehr Performance, Produktivität und Flexibilität im täglichen Entwicklungsalltag.

Eigentlich – so schien es – war das Thema Versionskontrolle in der Microsoft-Welt abgehakt: Team Foundation Version Control (TFVC) als ausgereiftes, stabiles System war gesetzt – als Open-Source-Alternative stand Apache Subversion bereit –, um den Rest des Kuchens stritten sich Systeme wie Perforce und Rational ClearCase. Doch dann kam Git und eroberte die Welt im Sturm: Nach der aktuellen Umfrage des Entwicklerportals Stack Overflow nutzen rund 87 Prozent der Entwickler Git; Subversion und TFVC landen mit 16,1 und 10,9 Prozent abgeschlagen auf Platz zwei und drei.

Was ist der Grund für den kometenhaften Aufstieg von Git? Was macht Git anders als die etablierten Platzhirsche? Und was gibt es zu beachten, wenn man das eigene Team auf Git migrieren will? Die wichtigsten Antworten auf diese Fragen möchte ich Ihnen im Folgenden liefern.

Zentral versus dezentral

Wer sich ein Git Cheat Sheet (wie es diesem Heft beiliegt) besorgt, könnte den Eindruck bekommen, dass Git eigentlich nur eine Variante des bereits bekannten Musters darstellt: Befehle zum Sichern des Versionsstands, zum Abrufen früherer Versionen sowie zum Verwalten von Varianten mittels Branching und Merging.

Aber der Schein trügt: Git funktioniert intern komplett anders, denn es ist als dezentrales System ausgelegt. Das bedeutet: Während TFVC und Subversion auf eine zentral verwaltete Datenbank setzen (Abb. 1), kommt Git auch gut ohne zentrale Datenbank aus. Jeder Nutzer hat vielmehr seine eigene Datenbank, unter Git „Repository“ oder kurz „Repo“ genannt (Abb. 2).

Abb. 1: Zentrale Versionskontrolle

Abb. 1: Zentrale Versionskontrolle

 

Abb. 2: Verteilte Versionskontrolle

Abb. 2: Verteilte Versionskontrolle

 

Unter Git arbeitet man die meiste Zeit mit dieser lokalen Datenbank und kann dann die erzeugten Änderungen (Commits) mit den anderen Projektbeteiligten austauschen. Obwohl Git dies nicht erfordert, wird hier dann doch wieder auf die bewährte Architektur mit einem Zentralserver (Blessed Repository) zurückgegriffen.

Schnell, sicher, flexibel

Das lokale Arbeiten bringt einige Vorteile mit sich: Git reagiert generell extrem schnell auf Benutzereingaben – es müssen ja nicht für jede Aktion langsame Netzwerkzugriffe durchgeführt werden. Diese gute Performance ist in der täglichen Praxis deutlich spürbar.

„Völlig losgelöst“ vom Server arbeiten zu können, erhöht auch die Flexibilität bei der Arbeit mit der Versionskontrolle. Kein Netzwerk? Kein Problem, auch wenn man an einem Ort am Sourcecode arbeitet, an dem keine Verbindung zum Server besteht. So ist es beispielsweise im Zug, in abgeschotteten Sicherheitsbereichen, bei Ausfall der DSL-Leitung und in ähnlichen Szenarien trotzdem möglich, den vollen Funktionsumfang der Versionsverwaltung zu nutzen – ein Plus für Service-Ingenieure, Consultants und alle anderen örtlich mobilen Entwickler.

Ein weiterer Bonus der dezentralen Auslegung von Git: Änderungen am Repository sind zunächst einmal privat, bis sie auf den Server übertragen werden. So ist es unter Git üblich, bei der Arbeit eigene, private Branches anzulegen, die vor der Übernahme in das zentrale Repository oft auch wieder gelöscht werden. So lassen sich im Alltag leicht Experimente am Code vornehmen, die dann sehr einfach wieder zurückgerollt werden können – sozusagen ein „Undo auf Stereoiden“. Auch diese erhöhte Flexibilität bei der Codeerstellung ist ein Feature, das die meisten Git-Nutzer nicht mehr missen wollen.

Nicht zuletzt bietet die dezentrale Datenspeicherung auch noch einen weiteren Vorteil: Da die einzelnen lokalen Repos in der Praxis oft synchronisiert werden, hat jeder Entwickler sozusagen eine Sicherheitskopie, was zu einer extrem hohen physischen Datensicherheit führt – und das ganz ohne explizite Back-ups auf einem Server.

Clevere Datenspeicherung

Apropos Flexibilität: Um die dezentrale Datenspeicherung möglich zu machen, setzt Git auf ein flexibles grafenbasiertes Speichermodell. Die Versionsgeschichte wird durch eine einfach verkette Liste abgebildet, die einzelnen Nodes repräsentieren die Commits (Änderungsdatensätze) mitsamt der Metadaten wie Name, Datum und Eincheckkommentar. Branches und Label werden durch leichtgewichtige Pointer realisiert. Die Integrität der Commits wird durch Hash-Werte sichergesellt, die über jedes Commit berechnet werden und diese gleichzeitig eindeutig identifizieren (Abb. 3).

 

Abb. 3: Versionsgeschichte als Abfolge von Commits, identifiziert durch Hash-Werte

Abb. 3: Versionsgeschichte als Abfolge von Commits, identifiziert durch Hash-Werte

 

Dieses Speichermodell macht Git in jeder Hinsicht noch flexibler. Das Erstellen von Branches geht extrem schnell und einfach, da intern nur ein weiterer Listen-Pointer eingefügt werden muss. Die interne Datenstruktur von Git ermöglicht die Manipulation der Versionsgeschichte auf jede erdenkliche Weise. Commits können zusammengefasst, entfernt und verändert werden, durch spezielle Manipulationen am Datenmodell können „technische“ Commits, wie sie bei anderen Systemen beispielsweise beim Mergen zwangsläufig entstehen, komplett vermieden werden. Diese Commits sind deshalb oft unerwünscht, weil sie keine inhaltliche Weiterentwicklung des Codes darstellen, sondern einfach nur markieren, dass eine technische Aktion wie ein Merge (Zusammenführen von Branches) oder ein Revert (Rückgängigmachen von Änderungen) auf dem Repo durchgeführt wurde.

Dadurch ist es unter Git möglich, eine sehr saubere und aufgeräumte Versionsgeschichte zu erstellen. Diese ist dann sehr gut les- und wartbar – im Gegensatz zur oft chaotischen Historie konventioneller Systeme. Viele Git-Nutzer sehen die Versionsgeschichte deshalb als organisch entstandenes Changelog an, das die logisch-semantische Projektgeschichte erzählt, und investieren entsprechend viel Aufwand in dessen Pflege.

Power und Komplexität

Doch, um es mit den Worten von Spidermans Onkel zu sagen: „With Great Power Comes Great Responsibility“. Das clevere Datenmodell bedeutet eben auch, dass ein erhöhter Lernaufwand nötig ist, um mit Git sicher und produktiv arbeiten zu können. Die vielen Möglichkeiten möchten beherrscht werden, und das geht nicht ohne ein intensives Studium der internen Funktionsweise von Git.

Viele Einsteiger stellen fest, dass der Einstig zwar sehr leichtfällt, es aber eine unsichtbare Barriere gibt, auf die man dann trifft, wenn man fortgeschrittene Techniken anwenden will oder in ungewohnte Situationen gerät. Auch ist es bei Git durchaus möglich, Daten zu „verlieren“. Meistens sind diese dann nicht wirklich gelöscht, aber bedingt durch den aktuellen Zustand des Datenmodells gerade einfach nicht sichtbar. Git überrascht Anfänger oft mit nicht gerade intuitivem Ausgang von Operationen – etwa, wenn nach Anzeige eines historischen Commits die neueren Commits verschwunden zu sein scheinen. Ich habe einmal in einem Forum gelesen: „Git can smell your Fear!“. Zudem ermöglicht Git es, bestimmte Operation „mit Gewalt“ durchzuführen, die bei den Mitbewerbern schlicht und ergreifend unmöglich sind – der Parameter –force macht’s möglich. Wer hier nicht genau versteht, was er oder sie tut, und einfach blind einem Rezept aus dem Internet folgt, läuft unter Umständen geradewegs ins Verderben. Also ist eine kurze, intensive Lernphase für jeden Ein- und Umsteiger Pflicht (Kasten: „Der 3-Schritte-Plan zum Umstieg“).

Der 3-Schritte-Plan zum Umstieg

  1. Informieren und Lernen: Das beste Buch zu Git („Pro Git“) findet sich auf der offiziellen Git-Website – auch als E-Book für alle gängigen Reader. Ein sehr gutes Tutorial bietet auch die Firma Atlassian auf ihrer Website – und es gibt zahlreiche Videotutorials und Quickstarts. Wichtig: Nicht nur Befehle lernen, sondern sich intensiv mit der Funktionsweise von Git vertraut machen. Git ist anders!
  2. Üben: Es empfiehlt sich, zunächst mit der Kommandozeile und einem einfachen Projekt zu üben, bis man die grundlegenden Operationen sicher beherrscht. Eine große Hilfe hierbei ist das kleine Tool GitViz, das die internen Vorgänge in einem Git-Repo visualisiert und so beim Verständnis hilft.
  3. Migrieren: Es ist möglich, Datenbanken von bestehenden Systemen wie Subversion und TFS nach Git zu migrieren – Git bietet direkten Support für den Import von SVN-Repos und auch Team Foundation Server hat eine eingebaute Importfunktion (allerdings nur für maximal 30 Tage Versionsgeschichte). Open-Source-Projekte wie beispielsweise git-tf helfen weiter. Viele Teams checken den Sourcecode aber einfach zu einem Stichtag aus dem bestehenden System aus und in Git wieder ein – so gibt es zwar einen Bruch in der Historie, aber dafür ist der Aufwand minimal. Das alte System kann dann zur Referenz in einen Read-only-Modus versetzt werden.

Plattformübergreifend

Git hat seinen Ursprung in der Linux-Welt. Es wurde als Ersatz für das bis dahin vom Linux-Kernel-Team genutzte BitKeeper (einem kommerziellen Pionier der dezentralen Versionsverwaltung) entwickelt. Die Linux-Gemeinde hatte sich mit dem Hersteller von BitKeeper überworfen und brauchte eine Alternative. Der Legende nach schloss sich Linus Thorwalds im stillen Kämmerchen ein und codierte die erste Version von Git in wenigen Tagen kurzerhand selbst.

Aufgrund der offensichtlichen Vorteile verbreitete sich das System sehr schnell. Überall auf der Welt fanden sich Mitarbeiter für die Weiterentwicklung – und innerhalb weniger Jahr hatte sich Git zum De-facto-Standard entwickelt. Heute sind Git-Implementierungen und Clients für praktisch alle wichtigen Betriebssysteme und integrierten Entwicklungsumgebungen verfügbar (Kasten: „Gute Git-Clients“). Git ist schnell, kompakt, einfach zu installieren und sofort einsetzbar. Sämtliche Operationen lassen sich über die Kommandozeile ausführen und es gibt zahlreiche freie und kommerzielle graphische Git-Clients für Windows, Mac, Linux und Co. Egal ob Visual Studio, Visual Studio Code, Eclipse, Android Studio oder XCode – überall ist die integrierte Git-Unterstützung längst Standard.

All das macht Git auch in der aktuellen Cross-Plattform-Entwicklungswelt zu einem idealen Tool. Unter Windows mit Xamarin entwickeln, auf einem Mac bauen und im Apple Store veröffentlichen? Kein Problem. Ein zentrales Repo für alle Skripte im Unternehmen, egal ob Bash oder PowerShell? Kein Problem! Git standardisiert die Welt der Versionsverwaltung.

Gute Git-Clients

Atlassian Sourcetree: Kostenlos nach Registrierung, verfügbar für Windows und Mac; der Klassiker unter den grafischen Git-Clients. Bietet alle Grundoperationen in einer relativ modernen Oberfläche, enthält aber keinen Merge-Editor (Abb. 4).

Abb. 4: Atlassian Sourcetree

Abb. 4: Atlassian Sourcetree

 

fournova Tower: 59–79 € pro User und Jahr; ursprünglich nur für Mac erhältlich, jetzt auch mit einer Windows-Version vertreten; sehr intuitiv mit guter Übersicht bei anspruchsvollen Operationen wie Merges (Abb. 5).

Abb. 5: fournova Tower

Abb. 5: fournova Tower

Axosoft GitKraken: 49 $ pro User und Jahr; frei verfügbar für nichtkommerzielle Arbeit und Open Source; erhältlich für Windows, Mac und Linux (Abb. 6).

Abb. 6: Axosoft GitKraken

Abb. 6: Axosoft GitKraken

Grenzen und Fallstricke

Wo Licht ist, ist auch Schatten. Erwähnt habe ich schon, dass Git eine steile Lernkurve hat. Weitere Limitationen liegen genau in dem oben gelobten dezentralen Datenmodell. Was, wenn mein Repository sehr groß ist und ich es nicht in kleinere, modularere Teile aufspalten kann? Schließlich muss das Repo auf jedem Entwicklerrechner repliziert werden und dort der entsprechende Speicherplatz zur Verfügung stehen. Was das bedeutet, zeigt sich an einem extremen Beispiel: Das Windows-Team bei Microsoft wollte auf Git umsteigen – und musste feststellen, dass dies aufgrund der Größe des monolithischen Windows-Sourcecodes mit 3,5 Millionen Files und 300 GB Repo-Größe praktisch unmöglich war. Operationen dauerten teils Stunden – ein unhaltbarer Zustand. Microsoft reagierte auf die Probleme mit der Entwicklung von Git Virtual File System – einer Erweiterung von Git, die das System zumindest teilweise wieder in eine Client-Server-Software zurückverwandelt.

Der Prozess der Pull Requests ist zum Quasistandard in Softwareteams geworden.

GitHub empfiehlt, ein einzelnes Repo unter 1 GB und einzelne Files unter 100 MB zu halten – klassische Versionskontrollsysteme ermöglichen hingegen riesige Petabyte-Versionsdatenbanken – schließlich können Nutzer hier auch nur wenige Files aus dem Zentralserver auschecken, ohne gleich die ganze Datenbank kopieren zu müssen.

Zugegeben, auch unter Git existieren teilweise Lösungen für dieses Problem – Stichworte sind hier Grafting und Shallow Checkouts, Git Submodules und Subtrees. Diese Workarounds sind aber nur bis zu einem gewissen Grad praktikabel und performant. Wer also sehr große Repos hat, sollte sich den Umstieg auf Git gut überlegen und zunächst einmal Performancetests durchführen.

Ein weiteres Feature, das Git prinzipbedingt nicht unterstützen kann, ist das exklusive Auschecken von Dateien (Check-out Locks), sodass diese nur von einer Person zu einem Zeitpunkt geändert werden können. Gerade CAD- und Engineering-Systeme verlassen sich oft noch auf diese Funktionalität, die nur bei den klassischen Versionskontrollsystemen zu haben ist.

Neue Workflows

Die neuen technischen Möglichkeiten von Git ebneten den Weg für neue Workflows in der Teamzusammenarbeit. Kollaborationsplattformen wie GitHub und Azure DevOps (vormals Team Foundation Server) bieten neue Wege, die Qualität und Transparenz von gemeinsam erstelltem Code zu steigern. Der Prozess der Pull Requests, ebenfalls aus der Open-Source-Szene übernommen, ist zum Quasistandard in modernen Softwareteams geworden. Dabei wird zunächst dezentral an Features und Bugfixes in eigenen, sogenannten Topic Branches gearbeitet – die Überführung in geschützte, qualitätsgesicherte Codelinien geschieht dann über einen kollaborativen Prozess, in dem automatisierte Tests und Builds ausgeführt werden können und das Team den Code in gemeinsamen Reviews bewerten und bearbeiten kann. Pull Requests sind kein Teil von Git, werden aber durch die Flexibilität der Git-Architektur erst praktikabel.

Fazit: Widerstand ist zwecklos

Git ist ein schnelles, leistungsfähiges und revolutionäres System zur Versionskontrolle, das sich in der Softwareindustrie durchgesetzt hat. In Zukunft dürfte Git das faktische Monopol für Versionsverwaltung besitzen. Wer sich noch nicht mit Git beschäftigt hat, sollte das schnell nachholen – es lohnt sich. Mit dem nötigen Respekt vor der Mächtigkeit des Systems, ein bis zwei Tagen Studium oder Seminar und ein bis zwei Wochen Zeit für die Umgewöhnung gelingt der Umstieg sicher und schnell. Go Git!

Uwe Baumann

Uwe Baumann ist ausgewiesener Experte für Microsoft Visual Studio, ALM und .NET. Seit 1999 begleitet er die verschiedenen Technologien zur Softwareentwicklung in der Microsoft-Welt. Als ALM Consultant und strategischer Technologieberater bei der artiso solutions GmbH untertützt er mit seiner umfassenden Erfahrung Kunden dabei, den Herausforderungen der modernen Softwareentwicklung zu begegnen.