Versioniert, ihr Narren!

27 February 2018

22 Minuten Lesezeit
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!

Über diesen Artikel

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

  • Die einfachste Variante, um Git auf Linux zu installieren, ist über einen Paketmanager. Hier der Befehl für ein Debian System: $ sudo apt-get install git
  • Auf dem Mac bietet sich dieser Installer an: sourceforge.net
  • Für Windows empfehle ich das msysGit Projekt, da neben der Version für die Kommandozeile auch eine grafische Oberfläche mit installiert wird: msysgit.github.com
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.

Die Shell, oder: Wo jetzt?

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.

Doch Stop! Was ist jetzt ein Repo?

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).

  • git init Wir gehen in den Ordner, der mit Git verwaltet werden soll. Dieser kann leer sein, muss es aber nicht. Nun ist also eine erste, initiale Version erstellt, aber noch ganz ohne Dateien.
  • git add [Dateiname] Haben wir nun eine Datei erstellt, fügen wir sie der Versionierung hinzu. Damit sagen wir Git, dass wir von nun an diese Datei ins Repo laden wollen, geschehen ist das aber noch nicht.
  • git status Schauen wir uns mal an, was Git gerade so sagt. Dort sehen wir, welche Dateien zum Git hinzugefügt werden, welche aktuell nicht getrackt sind und welche auch gelöscht wurden seit dem letzten Commit. Dort sollte nun auch unsere neue Datei unter added stehen.
  • git commit -m "Nachricht" Stichwort Commit: Bis jetzt haben wir Git gesagt, was es beim nächsten Commit machen soll, getan hat es all das noch nicht. Die Dateien sind gerade in der Stage (auch Index genannt). Das ist eine Zwischenstufe, die Dateien in der Zwischenstufe sind auf dem Stand, auf dem sie waren, als sie hinzugefügt wurden. Heißt also, wenn wir eine Datei nach dem add noch mal verändern, wird diese neueste Version nicht in der Stage sein, sie wird dort also nicht aktualisiert. Um sie zu aktualisieren, müssen wir sie erneut adden. Das -m "Nachricht" muss zwar nicht gemacht werden, ist aber sehr empfehlenswert. Hiermit fügen wir dem Commit eine Nachricht an, in der wir möglichst kurz (nur ein paar Worte) erklären, was dieser Commit beinhaltet (z.B. "Neue Datei hinzugefügt" oder "Problem xy gelöst").
  • git log Hiermit sehen wir eine Liste aller gemachten Commits mit dem Datum und ein paar Extradaten. Dort sollte jetzt also auch unser erster Commit erscheinen, sehr gut! (Mit Strg+C beenden wir diesen Befehl, dieser loggt nämlich die ganze Zeit weiter und muss erst beendet werden, bevor wir etwas anderes machen)
  • git add * Jetzt haben wir ein paar mehr neue Daten hinzugefügt und diese wollen wir auch alle dem Repo hinzufügen. Hier benutzen wir eine Wildcard: *
    Diese fügt einfach alle Dateien in diesem Order und allen Unterordnern hinzu. Wir können diesen Befehl also auch ganz zu Beginn einmal verwenden, wenn wir ein neues Repo in einem Ordner erstellt haben, in welchem schon zu versionierende Daten waren.
  • git rm [Dateiname] Wenn wir eine Datei nicht mehr versionieren wollen, löschen wir sie mit rm, damit verfolgt Git also nicht mehr die Änderungen dieser Datei.
  • git mv [Dateiname] [neuer Name] Wenn wir eine Datei umbenennen oder woanders schieben wollen, benutzten wir den move Befehl. Tun wir dies nicht über Git und benennen es einfach normal um, würde Git nach der alten Datei suchen und sagen, sie ist nun gelöscht. Gleichzeitig würde Git auch feststellen, dass es eine neue, noch nicht im Stage befindliche Datei gibt. Intern würde Git merken, dass es die gleiche Datei ist und somit intern auch nur mv anwenden, aber dennoch, lieber gleich richtig machen.
    Bei mv wie auch bei rm ist zu beachten, dass dies nicht der "normale" Bash-Befehl ist, sondern der von Git, damit eben auch Git diese Änderungen durchführt. Wir wollen ja in diesem Fall die Datei nicht einfach nur verschieben, wir wollen dies ja auch im Repo anwenden.
  • git add [Dateiname] (einer schonmal hinzugefügten Datei) Warum denn das? Wir haben diese Datei doch schon mal hinzugefügt? Das ist zwar korrekt, aber wir haben ja schon gelernt, dass add eine Datei nur in seiner Version zu diesem Moment hinzufügt. Wir müssen also jede neue Version einer Datei wieder hinzufügen, damit auch diese neuen Versionen im Repo auftauchen.
  • git commit -m "Nachricht" Da wir ja wieder ganz viel verändert haben, sollten wir all das nochmal committen, damit das Repo auf dem neuesten Stand ist.
  • git checkout -- [Dateiname] Wir haben nun an einer Datei etwas weiter gearbeitet, aber wirklich zufrieden sind wir nicht mit dem Ergebnis, also setzen wir die Datei auf den letzten Stand im Repo (das ist also der letzte Commit). Achtung! Hiermit überschreibst du alle Änderungen an der Datei! Grundsätzlich gibt es in Git viele Sicherheiten, um Dateien auch wieder zurück zu bekommen, wenn sie ausversehen mal gelöscht wurden, doch dieser Befehl gehört zu denen, die mit Vorsicht zu genießen sind.
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.
In Case of Fire
In Case of Fire
(c) 2015 Louis-Michel Couture

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.

Was ist eigentlich GitHub?

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.).

  • git clone [URL] Mit diesem Befehl erstellt Git ein neues Verzeichnis in dem aktuellen mit dem Namen des Projektes und lädt alle Dateien aus dem Repo dort hinein. Alle? Ja, alle, denn das ist einer der großen Vorteile, wie eingehens erwähnt. Damit hat jede beteiligte Person zu jeder Zeit alle Versionen und könnte auch das Repo notfalls einfach wiederherstellen, sollte der Server ausfallen.
    • Beispiel: git clone https://github.com/Peyje/robotic-arm-control.git Hiermit klont ihr also das Repo zu einem meiner Projekte, welches auf GitHub gehostet ist. Das geht natürlich auch mit anderen Protokollen (wir verwenden hier HTTPS, SSH wäre auch eine Möglichkeit), aber fürs Erste reicht es zu wissen, dass es mit dem Link oben im Browser geht.
  • git remote Lassen wir uns mal alle Remotes anzeigen, die Git aktuell so kennt. Remotes bezeichnet hier Remote Repositories, also Versionierungen des Projektes, die sich nicht auf dem Rechner befinden. Aktuell sehen wir dort nur Origin, das ist der originale Remote, also der, von dem wir geklont haben. Mit der Flag -v (einfach hinter den Befehl schreiben und ausführen) wird uns auch noch der Link dazu angezeigt.
  • git pull Nachdem wir eine Kaffeepause gemacht haben und bevor wir aber mit der Arbeit anfangen, wollen wir erstmal unsere lokalen Daten aktualisieren. Wir pullen also die neuesten Änderungen und mergen (also kombinieren) sie direkt mit unserem lokalen Repo. Da unsere letzte Version ja auch direkt von dem Remote kam, ist das gar kein Problem, etwas nervig kann es werden, wenn wir an unserer Version basteln, andere aber in der Zwischenzeit Neues pushen. Denn dann müssen diese kombiniert werden, es entsteht ein Merge-Konflikt. Dazu später noch etwas mehr, fürs aktuelle merken wir uns nur: Bevor wir irgendetwas machen, erstmal das Neuste pullen.
  • Workflow I An unserer Version arbeiten wir jetzt so lange, bis wir es mit dem Remote teilen wollen, dann geht es weiter.
  • git push origin master Wir sind also mit unseren Neuerungen zufrieden und wollen diese ins Remote laden. Dabei bezieht sich das erste Wort nach push auf das Remote, da wir hier nur unser original Remote haben, pushen wir auch auf dieses. Das Wort danach bezieht sich auf den Branch. Zu diesen kommen wir gleich, erstmal reicht es zu wissen, dass master der Hauptbranch ist und wir gerade auch auf diesen pushen wollen.
    Was genau haben wir gerade getan? Wir haben unsere Commits, die wir von unserer gepullten Version erstellt haben wieder auf das Remote gepusht. Damit ist also die neueste Version auf dem Remote unsere, wenn jetzt eine andere Person clone verwendet, würde sie auch diese Version erhalten.
  • git remote show [Remotename] Noch als kleiner Tipp dieses Kommando. Es zeigt Informationen zu dem Remote an, zum Beispiel auf welchen Branch man so pusht, wenn man pusht. Nun haben wir aber oft genug von diesen ominösen Branches gehört, machen wir mit ihnen weiter!
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

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.

  • git branch [Branchname] Erstellen wir also erstmal einen neuen Branch mit einem möglich passenden Namen. Nun haben wir also einmal den Master Branch und den Neuen. Aktuell sind beide noch auf dem gleichen Stand, das wollen wir aber ändern.
  • git branch Doch erst lassen wir uns alle verfügbaren Branches noch mal auflisten, nur zu Kontrolle.
  • git checkout [Branchname] Nachdem wir verifiziert haben, dass soweit alles passt, wechseln wir auf den neuen Branch, wir machen ein Checkout. Jetzt wird unser Arbeitsverzeichnis aktualisiert und alle Commits gehen nun in diesen Branch. Beim pushen sollte darauf geachtet werden, auch in den richtigen Remote-Branch zu pushen, nicht, dass die halbfertige Arbeit plötzlich als neuste Version auf dem Master-Branch des Remotes ladet.
  • Workflow I und II Nun arbeiten wir wie bekannt weiter.
  • git checkout master Wechseln wir zwischendurch mal wieder auf den Master-Branch. Jetzt wird das Arbeitsverzeichnis also auf diesen Branch zurückgesetzt.
  • git merge [Branchname] Nach einiger Zeit sind wird soweit, unser neues Feature auf den Master-Branch zu laden. Erstmal gehen wir sicher, das wir in dem Branch sind, in den wir alles Neue hinzufügen wollen, in unserem Fall also Master. Dann mergen wir! Wenn keiner am Master-Branch gearbeitet hat, sollte dies ohne Probleme übereingehen (Fast-Forward). Ist dies aber nicht der Fall, kommen wir zu dem altbekannten Merge-Konflikt. Hier müssen wir nun manuell überprüfen, ob die Änderungen, die passiert sind, während wir auf unserem anderen Branch gearbeitet haben, auch vereinbar sind mit unserem tollen neuen Feature. Möglicherweise wurde ja ein und die selbe Datei gleichzeitig verändert! Dies passiert entweder einfach in einem Texteditor oder mit extra dafür gemachten Mergetools (git mergetool) und kann durchaus kritisch sein, wenn in der Zwischenzeit viel verändert wurde. Darauf wollen wir nun aber nicht eingehen, bei kleinenen Projekten ist es eh meist nichts Großes und der Merge kann ungehindert stattfinden.
  • git branch -d [Branchname] Zu guter Letzt wollen wir noch den alten Branch löschen, da wir diesen ja nun nicht mehr brauchen, das ist aber vollkommen optional und müsste nicht geschehen.
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.