Versioniert, ihr Narren!

27 Feb 2018
Bei Versionierung geht es darum viele verschiedene Stufen und Meilensteine eines Projektes (von klein bis groß) zu speichern, als Backup sowie auch als spätere Referenz. Wahrscheinlich haben alle schon mal, wenn auch unbewusst, irgendwie versioniert, zum Beispiel durch einfaches Mehrfachspeichern einer Datei als "Text_1", "Text_1.1", "Text_2" und so weiter. Doch das geht auch viel effizienter und besser, beispielhaft mit Git. Doch wie genau, und was bitte ist "Git"?
Wer von einem simplen Word-Dokument, einem Ordner mit wichtigen Daten oder einer selbstgeschriebenen Software alle Zwischenversionen immer zur Hand haben will, ohne manuell jede Version neu zu speichern, kommt um eine ordentliche Versionsverwaltung nicht herum. Wenn dann diese Dateien noch mit anderen geteilt werden, paralleles Arbeiten ermöglicht werden UND all dies auch noch möglichst ressourcenschonend und effizient passieren soll, landen wir bei Git. Git ist ein eben solches, unglaublich mächtiges, Programm; doch hat es eine sehr steile Lernkurve. Dieser Artikel erklärt Git an typischen Workflows, auch (und gerade) für Nicht-Nerds.
XKCD-Comic zu Git
XKCD-Comic zu Git


Das ist Git. Es schafft Überblick über gemeinschaftliche Projekte durch ein wundervolles Baumdiagramm.

Cool. Wie nutzen wir es?

Kein Plan. Merkt euch einfach diese paar Kommandozeilen-Befehle und tippt sie ein, um zu synchronisieren. Wenn ihr einen Fehler bekommt, sichert eure Arbeit woanders, löscht das Projekt und downloadet es nochmal neu.

In Kürze: Was genau ist eine Versionsverwaltung, was ist Git?

Bei allen Projekten, ob nun im Softwarebereich oder nicht, empfiehlt es sich dringend, eine gute Dokumentation und eine Versionsspeicherung zu führen, um transparent zu arbeiten. Dies ermöglicht es, vergangene Änderungen wieder nachzuvollzuziehen und bei Bedarf auch wiederherzustellen. Für Software wird dies Versionskontrolle genannt. Wir haben also immer unsere eigentliche Hauptdatei, an der wir arbeiten und ältere Versionen, welche wir in einer Lokalen Versionsverwaltung ablegen. Sollen andere auch daran arbeiten, liegen diese Daten nicht nur lokal bei uns, aber auch auf einem Server, wo dann eine Zentrale Versionsverwaltung läuft und alle zugreifen können. Hier erhalten alle Teilnehmer immer nur die aktuellste Version, dies galt für viele Jahre als Standard, wenn versioniert wurde. Ein neuerer Ansatz ist, dass alle jederzeit alle Versionen bei sich haben, das wird dann Verteilte Versionsverwaltung genannt.
Und Git macht genau das, aber nicht so wie viele andere DVCS (Distributed Version Control System: Verteiltes Versionskontrollsystem). Git macht es besser. Aber eben auch so ganz anders, weswegen selbst viele erfahrene Programmierende zu Beginn etwas Schwierigkeiten haben. Was genau Git jetzt eigentlich macht, ist zu Beginn erstmal nebensächlich, wir wollen nun direkt starten!

Zu Beginn sei gleich gesagt, dass dieser Eintrag Git und dessen Interna nicht in Gänze erklären wird, nicht mal im Ansatz. Git ist unglaublich komplex und durchaus anspruchsvoll. Aber auch ohne all dieses Verständnis kann erfolgreich mit Git gearbeitet und viel Nutzen gezogen werden. Wer dann noch mehr aus seinen Projekten und Möglichkeiten mit Git schöpfen will, dem sei dies natürlich vollkommen offen (und es wird sich lohnen), aber auch ohne diesen Aufwand ist man anderen Versionskontrollen (schlimmer noch, vielleicht nur eine Dropbox, oder sogar nur ein Ordner auf dem PC als Versionierung) weit voraus. Weiterführende Links sind unten zu finden.

Einrichten von Git

Okay, fast. Erstmal müssen wir Git installieren und grob einrichten.

Installation

Unabhängig vom Betriebssystem empfehle ich wärmstens, Git, zumindest zu Beginn, per Kommandozeile zu steuern. Zwar sind grafische Oberflächen schön anzusehen, aber mit der Kommandozeile ist es dann doch noch schneller, es gibt die volle Kontrolle über Git und alle Nachrichten von Git kommen direkt und nicht über eine Abstraktionsebene. Wer schon etwas Erfahrung gesammelt hat und sich den Versionsverlauf aber einfach doch grafisch anzuschauen will, der sei natürlich davon nicht abgehalten.

Wie schon gerade erwähnt werden wir im weiteren Verlauf erstmal nur noch mit den Kommandos arbeiten und nicht mit einer grafischen Oberfläche. Linux User werden wohl wissen, was sie zu tun haben, aber ein paar Mac und gerade Windows User sind vielleicht nun etwas verwirrt. Ein kurzer Einschub zu der Shell und Kommandos:
Soll auf z.B. Windows einen Ordner geöffnet, etwas gesucht, oder überhaupt etwas getan werdem, geschieht das über die Programme und Oberflächen (die Fenster, also Windows, aha!). Das geht zwar auf vielen Linux Distributionen auch, aber dort geht es noch viel besser, indem bestimmte Kommandos in ein Terminal eingegeben werden. Das ist schneller, effizienter und sehr viel mächtiger, aber auch nicht ganz so einfach zu Beginn. Linux und OSX sind beides Unix-Systeme, sie haben also sehr viele gleiche Befehle, Windows als NT-System aber mal so gar nicht. Windows hat natürlich auch eine Kommandozeile (cmd.exe), aber bevor diese erlernt wird, kann auch einfach gleich was "Richtiges" gelernt werden. Ganz so schlecht, wie es jetzt klingt, ist Windows nun auch nicht (oder doch?), aber es gibt schon Gründe, warum mittlerweile offiziell auf jedem Windows-PC ein gesamtes Linux-Subsystem laufen kann.
Zurück zum Thema: Linux-User benutzen einfach ihre Bash, OSX-User das Terminal (CMD+Leertaste, Terminal eingeben) und Windows-User benutzen die Bash, die msysgit mitinstalliert hat (in dem Ordner, in dem gearbeitet wird Rechtsklick, Open Git Bash here). Und dort werden alle Befehle geschrieben!

Bash Befehle: Die Basics der Basics

Befehl Wirkung
cd change directory, danach einen Ordnernamen um da rein zu wechseln, .. um eine Ebene höher zu gehen
ls list, zeigt alle Dateien und Ordner im aktuellen Verzeichnis
mv move, gefolgt von dem Dateipfad und dem neu gewollten Dateipfad
mkdir make directory, erstellt ein neues Verzeichnis
rm remove, löscht die folgende Datei (ACHTUNG, hiermit kann viel gelöscht und zerstört werden!)
clear "räumt" die Bash auf, vorherige Befehle werden nicht mehr angezeigt
TAB Taste zur Vervollständigung, PFEILTASTEN um durch vorher schon verwendete Kommandos zu scrollen.

Konfiguration

Bevor wir mit der Verwendung von Git starten, sollten noch ein paar Dinge eingestellt werden.
Zuerst setzen wir den Namen des Benutzers mit: $ git config --global user.name "Name"(wobei wir Namein den " " mit dem des Benutzers (Dir!) ersetzen).
Das gleiche machen wir mit der Email-Adresse: $ git config --global user.email "Email"
Ohne das --globalwird dieser Wert nur für das aktuelle Projekt verändert (um zum Beispiel an einem einzelnen Projekt mit einem anderen Alias zu arbeiten).
Die Hilfe von Git zu einem Schlagwort gibt es über: $ git help <schlagwort>

Workflows

Los gehts! Wir gehen nach dem Prinzip Learning by doing, einfach erstmal etwas rumprobieren und simpel anfangen, die Komplikationen kommen schon von selbst, und dadurch auch das Verständnis. Auch wenn es sicherlich hilft zu verstehen, was Git eigentlich macht, wollen wir all das erstmal außen vor lassen, erstmal soll es überhaupt funktioneren.

Workflow I: Ein eigenes lokales Repo

Ziel: Wir legen auf unserem lokalen PC ein Repository an, versionieren da ein Dokument und arbeiten etwas dran.

Das Repository ist quasi ein Depot, also eine Art Datenbank, in der alle Daten in jeder Version vorliegen. Damit also alles getrackt und versioniert wird, wie es soll, laden wir die Dateien immer in das Repo. Für das Arbeiten mit Git bedeutet dies folgendes: Es gibt also ein Git-Verzeichnis, das Repository, in welchem alle relevanten Daten (die Dateien in der Datenbank selbst, aber auch Metadaten) gespeichert sind. Dann gibt es noch das normale Arbeitsverzeichnis. In dem Repository werden NIE Daten bearbeitet, es ist quasi das Archiv des gesamten Projektes. Sobald nun an einer Version gearbeitet wird, findet ein Checkout statt, dabei wird die gewollte Version geklont und im Arbeitsverzeichnis gespeichert. Hier können alle Daten modifiziert, gelöscht und erstellt werden. Am Ende laden wir dann die Daten wieder in das Repo (wir machen einen Commit, mehr dazu gleich).
Und so arbeiten wir einfach immer weiter, um ein lokales Repo zu führen und Daten zu versionieren. Das ist für uns schon mal ganz nett, aber eigentlich wollen wir ja all das mit anderen Leuten teilen oder die Arbeit von anderen anschauen und ebenso bearbeiten.

Damit im Falle eines Feuers deine Daten und Updates noch sicher und versioniert sind, erstmal committen und pushen! (Nach eigenem Ermessen folgen, könnte gefährlich werden)
Aber was genau ist eigentlich das pushen? Schauen wir uns das Arbeiten an Repos an, die eben nicht nur auf unserem PC liegen.

Workflow II: Ein öffentliches Repo klonen

Ziel: Wir schauen uns ein Projekt von einer anderen Person an und arbeiten an unserer eigenen Version. Dann erstellen wir ein eigenes öffentliches Repo und laden da ein paar Versionen hoch.

Wir wissen ja schon was Repos sind, jedoch sind diese bei uns bis jetzt immer lokal, also nur auf unserem Rechner. Um es mit anderen teilen zu können, müssen wir es erst auf einen Server laden. Ein Online-Dienst dafür ist GitHub: Hier können kostenlos Repos erstellt, Daten hochgeladen und somit die Arbeit auch mit anderen geteilt werden. Um seine Repos privat zu schalten, muss jedoch Geld bezahlt werden (Studierende erhalten dieses Feature umsonst).
Natürlich gibt es auch diverse andere Möglichkeiten, seine Repos online zugänglich zu machen (eine Alternative zu GitHub ist z.B. Gogs), jedoch ist GitHub die wohl meist benutzte Möglichkeit, und dazu hat GitHub noch ein paar nette Extrafeatures (Kanban-Board, Issue-Tracker, etc.).
Die hier genannten Befehle sind wirklich noch sehr Basic, aber dennoch, für die ersten Versuche und kleine Projekte mit nur einem oder zwei Beteiligten reicht es vollkommen aus. Solltet ihr aber anfangen wollen, professioneller mit Git zu arbeiten (oder zumindest so zu tun, als wäre man professionell..), wird durchaus noch mehr benötigt. Zum Beispiel: Wann verwende ich fetch (hier werden die neusten Änderungen nur gedownloadet, aber noch nicht in unseren Arbeitsbereich geladen) oder was hat eine Gabel mit Git zu tun? (Bei GitHub word ein Repo geforkt , wenn die Berechtigungen zum Arbeiten daran nicht da sind, es wird ein eigenes privates Repo erstellt, nach Abbild vom Originalen).

Workflow III: Mit Branches arbeiten

Ziel: Wir arbeiten an einem Feature fernab von der Hauptarbeitsstruktur und implementieren es dann am Ende wieder in dem Hauptstrang.

Branches sind, wie der Name schon sagt, Verzweigungen. Hierbei wird die aktuelle Version erst dupliziert, sodass dann parallel an beiden gearbeitet werden kann, ohne das jeweils Andere zu beinflussen. So können verschiedene Features simultan und unabhängig implementiert und entwickelt werden, bevor sie am Ende wieder in den Master-Branch eingefügt (gemerged) werden. Dies ist eine, wenn nicht sogar die, größte Unterscheidung zu anderen Versionierungsoftwares, denn Git löst dies besonders unkompliziert und gut.
Branches sind eine super Möglichkeit, an mehreren Ideen gleichzeitig zu arbeiten und seine Produktivität zu steigern. Oder auch, um einfach etwas auszuprobieren, ohne die Sorge, etwas kaputt zu machen. Wenn wir also mal sehen wollen, wie unser wundervoll selbstgeschriebenes Programm so aussieht, wenn jede Schriftart mit Comic Sans ausgetauscht wird, dann erstellen wir doch einfach mal den Branch "butwhy". Nachdem wir dann bemerkt haben, wie bescheuert die Idee war und wir eine Pause brauchen, löschen wir diesen ganz schnell wieder! (Nein, wir werden ihn nicht mergen, nicht Comic Sans, nein!)

Workflow IV: Und nun?

Nun heißt es: Einfach weitermachen! Das meiste wird schon klappen, und wenn dann doch mal nicht, dann gibt es Websiten wie StackOverflow , wo deine Frage mit an Sicherheit grenzender Wahrscheinlichkeit schon mal gestellt wurde. Falls du dich fragst, ob es ein bestimmtes Feature gibt, oder ob etwas vielleicht noch besser umsetzbar ist: Wahrscheinlich, schau einfach mal hier nach: git-scm . Und damit man nicht immer alle Befehle gleich wieder vergisst, hier ein Cheatsheat.

Inside Git

Etwas Theorie. Es kann nicht schaden, zumindest grob zu verstehen, wie Git jetzt eigentlich arbeitet. Aber auch hier verweise ich auf das oben genannte PDF, das wird es wohl besser erklären als ich, ausführlicher allemal. Dennoch gibt es hier eine ganz grobe Zusammenfassung:
Viele andere Versionierungssoftwares speichern nur die Diffs (Änderungen), Git dagegen erstellt Snapshots (Abbilder). Diese sind komplett eigenständige Versionen, dabei sind nicht veränderte Daten nicht erneut gespeichert, aber es wird auf sie referenziert, wodurch Speicherplatz nicht unnötig verbraucht wird. Der wohl größte Vorteil ist dabei, dass die Dateien lokal vorliegen und somit auch ohne Internetanbindung am Projekt gearbeitet und auf vorherige Versionen zugriffen werden kann. Git kennt bei Allem drei verschiedene Zustände für Dateien: staged, modified und committed. Eine Datei ist modified, wenn an ihr etwas verändert wurde, sie liegt also nicht mehr in dem Zustand vor, wie sie in der aktuellsten Version gespeichert ist. Sie ist staged, wenn wir sie mit add hinzugefügt haben. Sie liegt also quasi, wie auf einer Bühne, bereit zum committen. Eine Datei ist committed, wenn sie zur Datenbank hinzugefügt wurde. Nachdem also eine Datei bearbeitet wurde (also modified ist), findet bestenfalls auch ein Commit statt, hierbei erstellt Git einen Snapshot, welcher im Git-Verzeichnis gespeichert wird.
Bei einem Commit wird ein Objekt erstellt, welches auf den jeweiligen Snapshot der Daten "zeigt". Somit hat ein Commit (abgesehen vom Ersten) immer so genannte Parent-Commits, dies sind die vorherigen Commits. Bei einem neuen Branch wird nun ein neuer Zeiger erstellt, welcher am Anfang noch auf den gleichen Commit zeigt, wie der originale Branch. Wenn jetzt Änderungen durchgeführt werden, bewegen sich diese Zeiger unabhängig voneinander, da aber Git eben alle Versionen immer gespeichert hat, kann sehr schnell und einfach wieder zu einem anderen Branch gewechselt werden, wodurch die Dateien wieder auf den Zustand gesetzt werden, wie sie dort eben im letzten Commit waren.

Das soll es fürs Erste gewesen sein! Wie Git irgendetwas wirklich genau macht, wissen wir nun noch nicht, doch das wissen ehrlich gesagt die wenigsten (und ich zähle mich nicht dazu, nicht mal im Ansatz). Ich kann hier nur dafür plädieren, sich weiter einzulesen und sein Git-Game stetig zu verbessern. Und selbst wenn nicht, allein diese Basics sollten einem das Leben sehr erleichtern, wenn man nicht so gerne panisch in seiner Dropbox nach "Projektarbeit_1.5.1.3.doc" sucht, weil irgendwie ein ganzes Kapitel seiner Arbeit verloren gegangen ist.