Commit c90159fc authored by Lukas Nagel's avatar Lukas Nagel
Browse files

fix issues brought up in review

Fixed:
  * Nutzungshinweise: Projekt in GitHub anlegen
  * Rechtschreibung
  * Schnappschuss kursiv gesetzt, Konsistenz mit anderen Fachbegriffen
  * Zentrale Topologie kurz erklärt
  * Shallow Clone erläutert
  * Missverständliche Passage umgeschrieben: Konflikte werden durch Sperren
    nicht gelöst, sondern von vornherein verhindert
  * Fast-Forward-Merge ist hoffentlich besser verständlich
  * Erwähnung von CI/CD entfernt: Missverständlich
  * Allgm. Umformulierung komisch klingender Sätze

Wont Fix:
  * Wortwahl (Ugs.): ,,Schnappschuss". Schnappschuss ist der korrekte
    deutschsprachige Fachbegriff
  * Verbreiteten Begriff ,,Branch" anstatt umgangssprachlichem ,,Zweig"
    verwenden: Zweig ist korrekter deutschsprachiger Fachbegriff.
  * Wortwahl (Ugs.): ,,Spitze". So wird nun mal das Ende eines Zweiges
    bezeichnet.
  * Wie ist Git in CI/CD Werkzeuge integriert?
    Aber äußerst interessant Konzept, da Git[Hub] für viel Technologien
    angewendet werden kann.
  * Eingehen auf GUI's. Die schiere Menge an GUI's macht dies unpraktikabel
    und unmöglich zu verallgemeinern. Auch die CLI Befehle wurden im Hauptteil
    bewusst nicht verwendet, sondern die Operationen genannt, da diese
    ja auch so in GUIs umgesetzt werden (sollten?)
    Programmierumgebungen enthalten *Integration* nicht *Implementation*
    von GIT, die GIT Befehle versteckt, aber trotzdem verwendet.
  * In ,,Vorstellung der Probleme" wird bereits das Kernkonzept zur Lösung
    dargestellt. Nicht sicher wie es gemeint war.
parent ea8b7070
......@@ -8,4 +8,3 @@
*.out/
.docker
example/example.tar.gz
paper/paper.bib
......@@ -78,19 +78,16 @@ $(versionsgraphen) git-object: grafiken/versiongraph.tex
$(presentation): $(grafiken) $(bilder) presentation/theme.tex
$(paper): paper/paper.md $(grafiken)
paper/paper.md: literatur.yaml
paper/paper.md: references.bib
example/example.tar.gz: $(example)
tar -acf $@ $^
paper/paper.bib: references.bib
cp $< $@
# Generic Recipes
%.tex: %.md %.bib
pandoc --bibliography=$(*F).bib --biblatex -s -o $@ -i $<
%.tex: %.md
pandoc --biblatex -s -o $@ -i $<
%.pdf: %.tex
@echo "make: Entering directory '$(@D)'"
......
---
title: Versions Kontrolle mit Git und GitHub
title: Versionskontrolle mit Git und GitHub
author: Lukas Nagel, (7126709)
date: IT Technologie Trends WS21/22
abstract: |
In der Entwicklung von und Zusammenarbeit an Projekten, ist es Notwendig
die Veränderung die zu dem aktuellen Zustand geführt haben nachzuvollziehen
und untereinander auszutauschen.
Ohne Versionsverwaltung ist es sehr Zeitaufwändig nachzuvollziehen wer welche
Änderung und wann vollzogen hat.
Git bietet dazu einen Mechanismus Versionen mit Informationen zum Autor,
In der gemeinsamen Entwicklung von Projekten,
ist es notwendig, die Veränderungen, die zu dem aktuellen Zustand geführt haben,
nachzuvollziehen und untereinander auszutauschen.
Ohne Versionsverwaltung ist es sehr zeitaufwändig nachzuvollziehen,
wer welche Änderung vollzogen hat,
insbesondere in welchem Zeitraum und zu welchem Zweck.
Git bietet dazu einen Mechanismus, um Versionen mit Informationen zum Autor,
Zeit und einer Beschreibung anzulegen.
GitHub bietet auf den Git Mechanismen aufbauend eine Plattform zum
auszutauschen von Änderungen sowie zum veröffentlichen von Projekten.
GitHub stellt, auf den Git-Mechanismen aufbauend, eine Plattform zum
Austausch von Änderungen sowie zum Veröffentlichen von Projekten bereit.
Dies ermöglicht eine einfache Zusammenarbeit an Projekten
und Zugang zu Informationen.
fontsize: 11pt
geometry:
- left=2.5cm
- right=2.5cm
papersize: a4
classoption: twocolumn
bibliography: literatur.yaml
classoption:
- titlepage
- twocolumn
bibliography: references.bib
lang: de-DE
link-citations: true
header-includes: |
......@@ -30,34 +34,34 @@ header-includes: |
# Motivation
Während des Studiums fallen häufig Aufgaben an, bei denen es Notwendig
ist Dokumente zu erstellen und Software zu implementieren.
Dies erfolgt häufig in räumlich und zeitlich getrennter
Während des Studiums fallen häufig Aufgaben an, bei denen es notwendig ist,
Dokumente zu erstellen und Software zu implementieren.
Dies erfolgt häufig, in räumlich und zeitlich getrennter,
Zusammenarbeit mit Kommilitonen.
Dabei ist es Sinnvoll Änderungen an den benötigten Textdateien
Einfach nachvollziehen und bei Bedarf zurücknehmen zu können.
Unabhängige Anforderungen in eigenen Kontexten zu entwickeln
und später explizit zusammenzuführen,
vermeidet weiterhin nicht funktionale Wechselwirkungen im Entwicklungsprozess.
Diese Art von Nebenläufigkeit spielt insbesondere
bei mehreren Mitwirkenden eine entscheidende Rolle.
Dabei ist es sinnvoll, Änderungen an den benötigten Textdateien
einfach nachvollziehen und bei Bedarf zurücknehmen zu können.
Nicht funktionale Wechselwirkungen im Entwicklungsprozess
lassen sich, durch die Verwendung von eigenen Kontexten für unabhängige Features,
vermeiden.
Diese Art von Nebenläufigkeit spielt insbesondere bei mehreren Mitwirkenden
eine entscheidende Rolle.
Versionsverwaltungssysteme dienen zur Erfüllung dieser Anforderungen,
Versionsverwaltungssysteme dienen der Erfüllung dieser Anforderungen,
indem sie das Erfassen, Dokumentieren und Verwalten von Änderungen
sowie das Abspalten und Zusammenzuführung paralleler Entwicklungszweige
sowie das Abspalten und Zusammenführen paralleler Entwicklungszweige
ermöglichen.
In diesem Bericht werden *Git*, zur Versionsverwaltung,
sowie die online Plattform *GitHub*[^1] vorgestellt.
Das Kommandozeilen Programm Git zeichnet sich durch
eine weite Verbreitung, verteilte Topologie und Effizienz,
insbesondere beim Verzweigen, aus.
GitHub ist mittlerweile der größte Hoster von git Projekten,
der zusätzlich eine Webbasierte Oberfläche und weitere Werkzeuge zur
In diesem Bericht werden *Git* zur Versionsverwaltung
und die online Plattform *GitHub*[^1] vorgestellt.
Das Kommandozeilenprogramm Git zeichnet sich durch
eine weite Verbreitung, verteilte Topologie, Effizienz und
schnelles Verzweigen aus.
GitHub ist mittlerweile der größte Hoster von Git-Projekten,
der zusätzlich eine webbasierte Oberfläche und weitere Werkzeuge zur
Projektplanung sowie Dokumentation anbietet.
[^1]: [https://github.com/](https://github.com/)
......@@ -66,70 +70,68 @@ Projektplanung sowie Dokumentation anbietet.
## Beispiel
Alice und Bob arbeiten für eine Vorlesung gemeinsam an einer Aufgabe,
für die einen Sortier Algorithmus implementieren sowie beweisen sollen.
Für den Beweis wollen sie ein Dokument mit LaTex verfassen
und der Algorithmus soll in Python implementiert werden.
Dafür fallen die Dateien `proof.tex` und `alog.py` an.
Beide möchten unabhängig an dem Projekt arbeiten, Fortschritte miteinander
teilen und eine Version zentral verfügbar haben um von Unterschiedlichsten
Geräten zu arbeiten.
Sie verwenden dazu Git und GitHub, da es einfach ist mit Git herauszufinden
was der andere an dem Projekt verändert hat und mittels GitHub können sie
sich austauschen.
Zusätzlich können sie mittel GitHub Actions das LaTex Dokument automatisch
kompilieren und so immer auf die PDF Version zugreifen und automatische
Tests laufen lassen, so das sicher gestellt ist, dass der Algorithmus
korrekt ist beziehungsweise zu sehen welche Fälle noch nicht funktionieren.
für die sie einen Sortieralgorithmus implementieren und beweisen sollen.
Für den Beweis wollen sie ein Dokument in LaTeX verfassen,
der Algorithmus soll in Python implementiert werden.
Dafür fallen die Dateien `proof.tex` und `algo.py` an.
Beide möchten, unabhängig und von vielen verschiedenen Geräten, an dem Projekt
arbeiten, aber müssen ihre Fortschritte miteinander teilen.
Zum Teilen des Fortschrittes verwenden sie GitHub,
da sie bereits Git verwenden, um Änderungen einzupflegen und mehrere Versionen,
des selben Projektes, zu verwalten.
Zusätzlich können sie mit GitHub Actions das LaTeX-Dokument automatisch
kompilieren und so immer auf die PDF-Version zugreifen.
Außerdem lassen sich automatische Tests ausführen,
die prüfen, ob der Algorithmus korrekt ist.
Alice legt nun ein Projekt auf GitHub an und beide laden sich das Repository
herunter.
Nun können sie inkrementell Absätze schreiben beziehungsweise Funktionen
Jetzt können sie inkrementell Absätze schreiben, beziehungsweise Funktionen
implementieren und ihren Fortschritt mittels eines Commits festhalten
und erläutern.
So kann Bob nachvollziehen was und warum Alice bestimmte Änderungen vorgenommen
hat.
So kann Bob nachvollziehen, was Alice verändert hat und wofür die Änderungen
vorgenommen wurde.
# Vorgänger Technologien
# Vorgängertechnologien
Das Konzept der Versionskontrolle besteht, unabhängig von Technologie,
Das Konzept der Versionskontrolle besteht unabhängig von der Technologie
bereits seit einiger Zeit.
Beispielsweise ließ sich vor dem Durchbruch digitaler Dokumente durch
Kohlepapier eine Kopie eines Dokumentes anlegen,
das dann in Ordnerschränke einsortiert wurde.
Auch heute ist ein Arbeitsablauf ohne besondere auf Versionsverwaltung
ausgelegte Werkzeuge verbreitet [@devsurvey].
Auch heute ist ein Arbeitsablauf, ohne besonders auf Versionsverwaltung
ausgelegte Werkzeuge, verbreitet [@devsurvey].
Bei diesem werden Revisionen mittels Sicherungskopien realisiert
und unter anderem über Netzwerkspeicher Mitwirkenden zugänglich gemacht.
und für die Mitwirkenden, unter anderem über Netzwerkspeicher,
zugänglich gemacht.
Dokumentation kann dann über Benachrichtigungen oder Notizen geschehen.
Solch ein Ablauf kommt schnell an seine Grenzen,
da hoher Aufwand an Koordination gepaart mit der Notwendigkeit von Konventionen
ein Massives Risiko für Fehler birgt.
Daher ist es nützlich Koordination und Konventionen
mittels Werkzeugen, sogenannten Versionsverwaltungssysteme (*VCS*),
umzusetzen beziehungsweise durchzusetzen.
Frühe zentrale Ansätze, wie z.B. CVS verfolgen ein analoges Modell,
Solch ein Ablauf erzwingt die Einhaltung gewisser Konventionen und erfordert
somit sehr aufwändige Koordination, ohne die schnell Fehler entstehen.
Daher ist es nützlich, Koordination und Konventionen
mittels Werkzeugen, sogenannten Versionsverwaltungssystemen (*VCS*), umzusetzen.
Frühe zentrale Ansätze, wie zum Beispiel CVS, verfolgen ein analoges Modell,
bei dem anstatt eines Netzwerkspeichers ein Server verwendet wird.
Mitwirkende holen sich von diesem die aktuellste Version,
auch *checkout* genannt, nehmen Änderungen vor und laden diese
wieder hoch, auch *checkin* oder *commit* genannt.
Der Server speichert dann diese neue Version so,
dass Vorherige erreichbar bleiben,
die Gesamtheit der Versionen wird als *Versionsgeschichte* bezeichnet
Der Server speichert diese neue Version,
sodass vorherige Versionen erreichbar und erhalten bleiben.
Die Gesamtheit der Versionen wird als *Versionsgeschichte* bezeichnet
und im *Repository* gespeichert.
Dieser Ansatz setzt eine *zentrale* Topologie, mit einem Server und mehreren
Clients, voraus.
Sobald mehrere Personen am selben Projekt arbeiten, kann es dazu kommen,
dass mindestend zwei Personen die selbe Datei bearbeiten.
Ohne einen Mechanismus um solche Konflikte zu beheben,
würden die zu erst eingecheckten Änderungen Überschrieben.
Strategien um dies zu vermeiden teilen VCS in
dass mindestens zwei Personen dieselbe Datei bearbeiten.
Ohne einen Mechanismus, um solche Konflikte zu behandeln,
würden die zuerst eingecheckten Änderungen überschrieben werden.
Strategien, um dies zu vermeiden, teilen VCS in
*optimistische* und *pessimistische* Systeme.
Letztere vermeiden Konflikte durch Sperren und Freigeben von Dateien,
setzen somit eine *zentrale* Topologie voraus.
Da viele diese Sperren als zu restriktiv ansehen,
Im pessimistischen Ansatz werden Konflikte von vornherein ausgeschlossen,
indem stets nur einem Mitwirkenden exklusiver Zugriff auf eine Datei gestattet
wird.
Da Viele diese Sperren als zu restriktiv ansehen,
nutzen zusätzlich zu den *verteilten* auch *zentrale* VCS nun meist
den *optimistischen* Ansatz, bei dem keine Sperren eingerichtet werden,
sondern etwaige Konflikte an unterschiedlichen Bereichen des Dokuments
......@@ -138,174 +140,181 @@ sondern etwaige Konflikte an unterschiedlichen Bereichen des Dokuments
Git gehört zu den *verteilten* Versionsverwaltungssystemen,
bei denen jeder eine Kopie des Gesamten Repository lokal gespeichert hat.
Weiterhin wird für jede Version ein Schnappschuss des gesamten Projektes
gespeichert und nicht nur wie bei anderen üblich die Unterschiede,
dadurch lassen sich Zustände sehr effizient wiederherstellen.
Dies erfordert bei größeren Projekten mehr Bandbreite und Speicher,
was durch einen sogenannten *shallow* clone umgangen werden kann.
bei denen jeder eine Kopie des gesamten Repository lokal gespeichert hat.
Weitere verteilte Systeme sind unter anderem BitKeeper,
dessen Lizenzwechsel die Entwicklung von Git veranlasste,
und Mercurial, das ein besseres Nutzererlebnis,
aber langsamere Operationen aufweisen soll.
Bei Git wird für jede Version ein *Schnappschuss* des gesamten Projektes
gespeichert, also eine Kopie des gesamten Arbeitsverzeichnisses.
Dem steht ein Ansatz gegenüber, bei dem nur die Änderungen zum Vorgänger
gespeichert werden, den sogenannten *Change Sets*.
Das Speichern von Schnappschüssen ermöglicht es,
Zustände sehr effizient wiederherzustellen [@hamano2006].
Jedoch erfordert diese Art von Repository bei größeren Projekten mehr
Bandbreite und Speicher.
Dieses Problem kann durch eine flache Kopie (engl. *shallow clone*)
umgangen werden,
indem nur eine vorgegebene Anzahl an Vorgängerversionen
und erst bei Bedarf frühere, also tiefere, Versionen herunterladen werden.
Weiterhin ist dieser Nachteil angesichts heutiger
Übertragungsgeschwindigkeiten und Speicherkapazitäten oft vernachlässigbar
[baerisch2005].
[@baerisch2005].
Lokale Repositories können untereinander synchronisiert werden,
dabei bezeichent man das entfernte Repository als *remote*.
Häufig gibt es ein Hauptrepository mit dem sich alle Mitwirkende
Lokale Repositorys können untereinander synchronisiert werden,
dabei wird das entfernte Repository als *remote* bezeichnet.
Häufig gibt es ein Haupt-Repository, mit dem sich alle Mitwirkende
synchronisieren [@haenel2015, S. 149].
Das lokale Repository enthält die gesamte Versionsgeschichte,
die somit ohne Verbindung zu einem Server verfügbar ist.
Weiterhin müssen Versionen nicht direkt in das Hauptrepository
Weiterhin müssen Versionen nicht direkt in das Haupt-Repository
eingepflegt werden, sondern können lokal gesammelt werden.
Dies erlaubt es ebenfalls die lokale Versionsgeschichte vor dem
synchronisieren mit dem remote, zu bearbeiten und commits in eine
Dies erlaubt es ebenfalls, die lokale Versionsgeschichte vor dem
synchronisieren mit dem remote zu bearbeiten und commits in eine
besser nachvollziehbare Reihenfolge zu bringen [@haenel2015, S. 126].
Ähnlich zu einem eigenen Entwicklungskontext pro Nutzer,
Ähnlich zu einem eigenen Entwicklungskontext pro Nutzer
erlaubt *branching* einen eigenen Kontext pro Feature.
Aus der Perspektive des Nutzers sind Zweige alleinstehende des Projektes
Aus der Perspektive des Nutzers sind Zweige alleinstehende Kopien des Projektes
[@baerisch2005].
Dabei wird von einen Hauptzweig,
nach git *Konvention* `master`,
Dabei wird von einem Hauptzweig, nach Git *Konvention* `master` genannt,
abgespalten und eine eigenständige Entwicklungslinie angefangen.
Diese lässt sich dann ähnlich wie Versionen unterschiedlicher Nutzer
zusammenzuführen [@haenel2015, S. 63].
Diese lässt sich dann, ähnlich wie Versionen unterschiedlicher Nutzer,
zusammenführen [@haenel2015, S. 63].
Für nahezu alle Versionsverwaltungssysteme gibt es auch einen Anbieter,
der das Hosting eines zentralen beziehungsweise Hauptrepository anbietet.
Für nahezu alle Versionsverwaltungssysteme gibt es einen Anbieter,
der das Hosting eines zentralen beziehungsweise Haupt-Repositorys anbietet.
Bei einigen werden zusätzliche Funktionen angeboten,
wie beispielsweise Wikis, Issue Tracker, Dokumentation
und Bereitstellung von Software Paketen [@haenel2015, S. 315].
Im traditionellen Ansatz wie er etwa von SourceForge[^2] verfolgt wird,
wie beispielsweise Wikis, Issue-Tracker, Dokumentation
und Bereitstellung von Softwarepaketen [@haenel2015, S. 315].
Im traditionellen Ansatz, wie er etwa von SourceForge[^2] verfolgt wird,
steht das Projekt im Vordergrund.
GitHub hingegen stellt den Nutzer in den Vordergrund,
in dem Projekte unter dem Namensraum eines Nutzers angelegt werden.
Dies spiegelt den verteilten Ansatz von Git wieder, in dem jeder Nutzer
nun neben seinem lokalen auch einen entferntes Repository zu Verfügung hat.
Eine Kopie eines Repositories auf GitHub wird als *Fork* bezeichnet
indem Projekte unter dem Namensraum eines Nutzers angelegt werden.
Dies spiegelt den verteilten Ansatz von Git wider, in dem jeder Nutzer
nun neben seinem lokalen, auch ein entferntes Repository zur Verfügung hat.
Eine Kopie eines Repositorys auf GitHub wird als *Fork* bezeichnet
und kann über die Weboberfläche angelegt werden.
Mittel *klonen* wird es dann lokal kopiert. [@blishak2016]
Mittels *klonen* wird es dann lokal kopiert. [@blishak2016]
Um Änderungen einzupflegen ist somit kein direkter Zugriff auf das
Hauptrepository notwendig.
Typischer Weise werden Änderungen aus einem Fork in das Hauptrepository
Haupt-Repository notwendig.
Typischerweise werden Änderungen aus einem Fork in das Haupt-Repository
mittels einer Anfrage, der sogenannten *Pull Request*, übernommen.
Der Name leitet sich von einem Git Kommando ab,
das zum erstellen einer Anfrage per E-Mail verwendet werden kann.
Der Name leitet sich von einem Git-Kommando ab,
das zum Erstellen einer Anfrage per E-Mail verwendet werden kann.
Der Austausch über E-Mail wird von einigen großen Projekten,
wie zum Beispiel Git selbst, verwendet [@haenel2015, S. 179],
wird aber nicht von GitHub unterstützt.
Neben der Webbasierten grafischen Oberfläche vereinfacht dies,
das einpflegen von Änderungen in Open Source Projekte,
wie zum Beispiel Git selbst, verwendet [@hamano2006],
jedoch nicht von GitHub unterstützt.
Neben der webbasierten grafischen Oberfläche vereinfacht dies,
das Einpflegen von Änderungen in Open-Source-Projekte,
verglichen mit früheren Ansätzen.
[^2]: [https://sourceforge.net/](https://sourceforge.net/)
Der Fokus auf Software Entwicklung in GitHub,
prägt sich ebenfalls in der Integration von CI/CD Werkzeugen.
Diese können verwendet werden um Tests auszuführen
Der Fokus auf Softwareentwicklung in GitHub
spiegelt sich ebenfalls in der Integration von Automatisierungswerkzeugen wider.
Diese können verwendet werden, um Tests auszuführen
und ausführbare Pakete zu erstellen.
Die Ergebnisse von Test können in Pull Request integriert werden
und helfen so Fehler vorzeitig zu identifizieren.
Dies lässt sich aber auch nutzten um Beispielsweise LaTex Dokumente
automatisch zu kompilieren und an das GitHub Projekt anzuhängen.
Git bietet mittels Hooks zwar schon seit längerem die Möglichkeit
Programme bei bestimmten Events auf dem Server auszuführen,
dies erfordert aber eine Individuelle nicht standardisierte Konfiguration
und einen eigenen Server.
Die Ergebnisse von Tests können in Pull Requests integriert werden
und helfen so, Fehler vorzeitig zu identifizieren.
Dies lässt sich aber auch nutzen, um beispielsweise LaTeX-Dokumente
automatisch zu kompilieren und an das GitHub-Projekt anzuhängen.
Zwar bietet Git mit Hooks schon seit Längerem die Möglichkeit,
Programme bei bestimmten Ereignissen auszuführen,
dafür wird aber eine individuelle, nicht standardisierte Konfiguration benötigt.
GitHub nutzt zur Bereitstellung ihrer Dienste, im Gegensatz zu GitLab oder SourceForge,
selbst nicht Quelloffene und unter proprietärer Lizenz stehende Software,
sodass eine eigene Instanz lediglich Kunden von GitHub Enterprise möglich ist.
GitHub nutzt zur Bereitstellung der Dienste,
im Gegensatz zu GitLab oder SourceForge,
selbst nicht quelloffene und unter proprietärer Lizenz stehende Software.
Daher ist eine eigene Instanz den Kunden von GitHub Enterprise vorbehalten.
# Vorstellung der Probleme
In diesem Bericht wird vorgestellt,
wie Git und GitHub die folgenden vier Problem löst.
wie Git und GitHub die folgenden vier Probleme lösen.
Bei der Bearbeitung von Dokumenten kommt es häufig zu kleinen Fehlern,
daher ist ein Mechanismus zum Rückgängig machen von Änderungen,
daher ist ein Mechanismus zum Rückgängig machen von Änderungen
in so gut wie jedem Textbearbeitungsprogramm integriert.
Ein solcher Mechanismus, der für die Gesamtheit aller Dateien
eines Projektes, unabhängig vom Textbearbeitungsprogramm und
Ein solcher Mechanismus, der die Gesamtheit aller Dateien
eines Projektes umfasst und unabhängig vom Textbearbeitungsprogramm sowie
über Rechnergrenzen hinweg funktioniert,
löst das Problem der *Wiederherstellbarkeit*.
Jeder Commit der Versionsgeschichte ist durch eine Adresse,
beziehungsweise Revisionsnummer, oder eine Referenz erreichbar und
kann auch partiell wiederhergestellt werden.
Jeder Commit der Versionsgeschichte ist durch eine Adresse, Revisionsnummer
oder eine Referenz erreichbar und kann, bei Bedarf auch nur partiell,
wiederhergestellt werden.
Sobald eine Änderung vorgenommen wurde,
soll dies einfach Sichtbar und mit Informationen zum Autor
und Zweck der Änderungen versehen sein,
dies löst das Problem *Nachvollziehbarkeit*.
Jeder Commit also jede Revision wird mit solchen Informationen versehen
und Änderungen werden durch Vergleichsfunktionen sichtbar.
soll dies einfach sichtbar und mit den notwendigen Informationen versehen sein,
die *Nachvollziehbarkeit* ermöglichen.
Jeder Git Commit, also jede Revision, wird mit solchen Informationen versehen
und Änderungen können durch Vergleichsfunktionen aufbereitet werden.
Auch Einzelnutzer müssen zum Beispiel ein Projekt an mehreren Geräten
bearbeiten oder auf einem Server sichern.
Aber vor allem Gruppen benötigen einen komfortable Mechanismus zum
Aber vor allem Gruppen benötigen einen komfortablen Mechanismus zum
*Austausch* von Änderungen.
In Git sind befehle zum Datenaustausch eingebaut
In Git sind Befehle zum Datenaustausch eingebaut
und GitHub bietet eine kostenlose Plattform zur Veröffentlichung.
Dabei kann es zu übertragungsproblemen kommen oder auf sonstige Weise
sich Daten ändern.
Ebenfalls könnten Antagonisten versuchen die Versionsgeschichte
Die Übertragung kann, durch Übertragungsprobleme oder auf sonstige Weise,
zu veränderten Daten führen.
Ebenfalls könnten Antagonisten versuchen, die Versionsgeschichte
so zu verändern, dass zum Beispiel Schadsoftware ausgeführt wird.
Dies soll erkannt werden, damit die *Integrität* gewährleistet ist.
Bei Git wird dies durch eine Kette von Kryptographischen Hashes erreicht.
Bei Git wird dies durch einen Baum aus kryptografischen Hashes erreicht,
diese Anordnung entspricht einem Merkle-Baum.
# Kernkonzepte
## Grundlegende Datenstruktur
Git speichert das Repository und Konfigurations Daten,
in der obersten Verzeichnisebene des versionierten Arbeitsverzeichnisses,
unter dem `.git` Verzeichnis.
Das Repository sowie die Konfigurationsdateien werden von Git im Verzeichnis `.git`,
in der obersten Verzeichnisebene des versionierten Arbeitsverzeichnisses, abgelegt.
Darunter befindet sich unter anderem die Datei `config`,
in der Einstellungen für das Repository gespeichert werden.
Die Datei `HEAD` enthält eine Referenz auf den aktuellen Zweig.
Zeiger auf die Commits, die den Spitzen der Zweige entsprechen,
sind in `refs` gespeichert, wobei lokale branches unter
sind in `refs` gespeichert, wobei lokale Zweige unter
`refs/head` und entfernte unter `refs/remotes/<remote>` gespeichert werden
[@haenel2015, S. 327].
Im Verzeichnis `objects` werden, unter ihrem SHA1 Hash,
Instanzen des universellen Datentyps *Objekt*,
Instanzen des universellen Datentyps *Objekt*
gespeichert.
Objekt können sich als *tree*, *commit* oder *blob* Objekte ausprägen.
Objekte können sich als *tree*, *commit* oder *blob* Objekte ausprägen.
Die Ausprägung wird als Text am Anfang der Datei festgelegt.
Das blob Objekjt speichert beliebige Byte folgen,
Das blob Objekt speichert beliebige Bytefolgen,
wie in der Regel den Inhalt von Dateien.
Tree Objekte bilden einen Datei- oder Verzeichnisnamen
auf die Referenz des entsprechenden blob beziehungsweise tree Objektes.
Tree Objekte bilden die Datei- oder Verzeichnisnamen eines Verzeichnisses,
auf die Referenz des entsprechenden blob beziehungsweise tree Objektes, ab.
Das commit Objekt wird für jede Revision angelegt
und enthält den Namen und die E-Mail des Autors,
eine Beschreibung, die Gründe für und die Änderungen an sich beschreiben sollte,
sowie eine Referenz auf beliebige viele Vorgänger commit Objekte.
eine Beschreibung, die die Gründe für und die Änderungen an sich
beschreiben sollte,
sowie eine Referenz auf beliebig viele Vorgänger-Commit-Objekte.
Bei keinem Vorgänger handelt es sich in der Regel um den ersten *Root-Commit*
eines Projektes,
bei einem Vorgänger um einem Inkrement
und bei mehreren um einen *Merge-Commit*,
eines Projektes und bei mehreren um einen *Merge-Commit*,
wobei die Vorgänger den Spitzen der zusammenzuführenden Zweige entsprechen
[@haenel2015, S. 50].
In Abbildung \ref{fig:objm} ist der Zusammenhang der Objekt Arten mit der Verzeichnisstruktur
schematisch dargestellt.
In Abbildung \ref ist der Zusammenhang der Objektarten mit der
Verzeichnisstruktur schematisch dargestellt.
![Git Objektmodell](../grafiken/git-object.pdf){#fig:objm}
......@@ -316,41 +325,42 @@ bezeichnet
und hat die im Folgenden erläuterten Konsequenzen.
Jedes mögliche Objekt wird höchstens einmal gespeichert,
da gleiche Objekte den selben Hash haben.
Daher wird auch kein Neues Objekt für Dateien beziehungsweise Verzeichnisse
angelegt, die sich nicht verändert haben.
Auch wenn zwei Dateien beziehungsweise Verzeichnisse den selben Inhalt haben,
da gleiche Objekte denselben Hash haben.
Daher wird auch kein neues Objekt für Dateien, beziehungsweise Verzeichnisse,
angelegt, die sich zwischen Versionen nicht verändert haben.
Auch, wenn zwei Dateien oder Verzeichnisse denselben Inhalt haben,
muss nur ein Satz Objekte gespeichert werden.
Weiterhin ändert sich am blob Objekt einer Datei beim Umbenennen nichts,
nur das tree Objekt wird modifiziert.
Dieses Konzept wird als *Deduplizierung* bezeichnet [@haenel2015, S. 37].
Dies Bedeutet aber auch das falls sich nur ein sehr kleiner Teil einer großen
Dies bedeutet aber auch, dass falls sich nur ein sehr kleiner Teil einer großen
Datei ändert,
werden zwei nahezu identische Objekte mit unterschiedlichem Hash angelegt.
zwei nahezu identische Objekte mit unterschiedlichem Hash angelegt werden.
Dies erfordert somit überproportional viel Speicher,
weswegen der Objektspeicher mittels *Deltakompression* komprimiert wird
[@chacon2014].
weswegen der Objektspeicher mittels *Deltakompression* komprimiert werden kann,
bei der lediglich die Unterschiede gespeichert werden, die als Deltas bezeichnet
werden [@chacon2014].
Der Hash eines tree Objektes wird auch über die Hashes der enthaltenen
tree und blob Objkete gebildet.
Und der Hash jedes Commit Objektes wird unter anderem über die Hashes
des tree Objektes und der Vorgänger Commits gebildet.
Somit ergibt sich eine Kette kryptographischer Hashes, wodurch die *Integrität*
tree und blob Objekte gebildet.
Und in den Hash jedes Commit-Objektes fließen unter anderem die Hashes
des tree Objektes und der Vorgänger Commits ein.
Somit ergibt sich eine Baum kryptografischer Hashes, wodurch die *Integrität*
des Projektverzeichnisses und der gesamten Versionsgeschichte sicherstellt wird
[@haenel2015, S. 42].
Eine Besonderheit von Git ist der Index, oder auch *Staging Area*, genannt,
Eine Besonderheit von Git ist der Index, auch *Staging Area* genannt,
der als Schnittstelle zwischen Arbeitsverzeichnis und Repository fungiert.
Änderungen aus dem Arbeitsverzeichnis werden zünachst mittels der Add
Operation im Index gesammelt und mittels der Commit Operation
Änderungen aus dem Arbeitsverzeichnis werden zunächst mittels der Add-Operation
im Index gesammelt und mittels der Commit Operation
in das Repository übernommen.
Der Index enthält für jede Datei eine Referenz auf ein Objekt,
dieses kann ein anderes sein als das der entsprechenden Datei im
Arbeitsverzeichnis oder Repository.
Mittels einer Add Operation werden Änderungen aus dem Arbeitsverzeichnis
Mittels einer Add-Operation werden Änderungen aus dem Arbeitsverzeichnis
in den Index übernommen und benötigte Objekte erstellt.
Mit der Reset Operation können Inhalte aus dem Repository in den Index
Mit der Reset-Operation können Inhalte aus dem Repository in den Index
und optional in das Arbeitsverzeichnis übernommen werden.
Somit lässt sich die nächste Version inkrementell erstellen
und muss nicht dem Zustand des Arbeitsverzeichnisses entsprechen
......@@ -359,16 +369,16 @@ und muss nicht dem Zustand des Arbeitsverzeichnisses entsprechen
## Versionsgeschichte als Graph
Dadurch das ein Commmit mehrere Vorgänger hat lässt sich die Versionsgeschichte
Dadurch, dass ein Commit mehrere Vorgänger hat, lässt sich die Versionsgeschichte
als gerichteter Graph ohne Zyklen (*DAG*) betrachten.
In Abbildung \ref{fig:graph} ist ein solcher abgebildet.
Ein Zyklus ist theoretisch nicht ausgeschlossen,
aber nur erschöpfende Suche möglich, da wenn sich zwei Commits gegenseitig als
Vorgänger haben sollen, für den jeweiligen Hash der jeweils andere
Hash bereits bekannt sein müsste.
aber nur durch erschöpfende Suche möglich,
da, wenn sich zwei Commits gegenseitig als Vorgänger haben sollen,
für den jeweiligen Hash, der jeweils andere Hash bereits bekannt sein müsste.
Die Knoten, wie in Abbildung \ref{fig:graph} zu sehen, entsprechen den Commits
und die Vorgänger Beziehung ist durch die Kanten ausgedrückt.
Zweige entsprechen in diesem Modell Zeigern auf Commits.
und die Vorgängerbeziehung ist durch die Kanten ausgedrückt.
Zweige entsprechen in diesem Modell Zeigern auf Knoten.
Das Verständnis vieler Operationen wird durch dieses Modell vereinfacht
[@haenel2015, S. 41].
......@@ -377,104 +387,118 @@ Das Verständnis vieler Operationen wird durch dieses Modell vereinfacht
## Verzweigung und Tags
Verzweigungen in Versionsgraph sind in Git sehr performant Umgesetzt.
Eine neuer Zweig erfordert lediglich das anlegen einer neuen Referenz,
also eine einfache Textdatei, in 'refs/heads'.
Diese Referenz enthält zunächst den Commit Hash des Verzweigungunspunktes.
Um zu diesem Zweig zu wechseln muss nun das Arbeitsverzeichnis so angepasst
werden, dass es dem Inhalt des Tree Objekts auf das der Commit Zeigt entspricht.
Verzweigungen im Versionsgraphen sind in Git sehr performant umgesetzt.
Ein neuer Zweig erfordert lediglich das Anlegen einer neuen Referenz,
also einer einfachen Textdatei, in 'refs/heads'.
Diese Referenz enthält zunächst den Commit-Hash des Commits, von dem abgezweigt
wird (engl. *fork point*).
Um zu diesem Zweig zu wechseln, muss das Arbeitsverzeichnis so angepasst
werden, dass es dem Inhalt des Tree-Objekts, auf das der Commit zeigt, entspricht.
Anschließend wird der HEAD auf den Zweig gesetzt.
Die Nächsten Commit Operation werden den neuen Zweig bewegen.
Das Zusammenführen von Anderen zweigen in den Aktuellen ist mit der Merge
Operation möglich.
Liegt der Commit auf den der aktuellen Zweig zeigt auf dem Pfad vom
zusammenzuführenden Zweig, so wurden auf dem aktuellen Zweig nach dem
Verzweigen keine Commits mehr vorgenommen.
Die nächsten Commit-Operationen, nach dem Wechsel, werden den neuen Zweig bewegen.
Das Zusammenführen von anderen Zweigen mit dem aktuellen ist mit der
Merge-Operation möglich.
Wurden seit dem Verzweigen keine Commits auf dem Aktuellen,
aber auf dem anderen Zweig vorgenommen, so liegt der aktuelle Commit auf dem Pfad
von der Spitze des anderen Zweiges zur Wurzel
(vergleiche Abbildung \ref{fig:ffmerge}).
In dieser Situation ist ein Vorspulen (*Fast-Forward-Merge*) möglich,
dabei wird der Aktuell Zeiger auf die Spitze des anderen Zweiges vor gespult.
dabei wird der aktuelle Zeiger auf die Spitze des anderen Zweiges ,,vorgespult".
In Abbildung \ref{fig:ffmerge} würde Zeiger *B* so verschoben,
dass er denselben Commit wie *A* zeigt.
Danach ist im Versionsgraphen keine Verzweigungsstruktur erkennbar,
da kein Merge-Commit angelegt wurde.
Sind auf beiden Zweigen Commits eingepflegt worden, so ist ein Merge-Commit
nötig.
Dieser erhält als Vorgänger beide Commits der Zweige und das Tree Objekt zeigt
auf einen Schnappschuss in dem Änderungen beider Zweige enthalten sind.
Wurden sich überschneidende Stellen verändert, so kann Git nicht automatisch
entscheiden wie die Änderungen vereinigt werden sollen.
Sind auf beiden Zweigen Commits eingepflegt worden, ist ein Merge-Commit nötig.
Dieser erhält als Vorgänger die Spitzen der Zweige und der Tree-Zeiger zeigt auf
einen Schnappschuss, in dem Änderungen beider Zweige zusammengeführt wurden.
Falls an sich überschneidende Stellen Änderungen vorgenommen wurden,
kann Git nicht automatisch entscheiden,
wie die Änderungen vereinigt werden sollen.
Daher muss dieser Konflikt manuell aufgelöst werden,
dazu können die Betroffenen Stellen in einem Textbearbeitungsprogramm
oder mit Grafische Werkzeuge, wie es zum Beispiel GitHub bereitstellt,
wozu Git Markierungen in den entsprechenden Dateien einfügt.
Dazu kann der Konflikt an den betroffenen Stellen in einem
Textbearbeitungsprogramm oder mit grafischen Werkzeugen,
wie es zum Beispiel GitHub bereitstellt,
gelöst werden.