-
1. Erste Schritte
- 1.1 Über Versionskontrolle
- 1.2 Eine kurze Geschichte von Git
- 1.3 Was ist Git?
- 1.4 Die Kommandozeile
- 1.5 Git installieren
- 1.6 Erstmalige Git-Einrichtung
- 1.7 Hilfe bekommen
- 1.8 Zusammenfassung
-
2. Git Grundlagen
-
3. Git Branching
- 3.1 Branches im Überblick
- 3.2 Grundlegendes Branching und Merging
- 3.3 Branch-Management
- 3.4 Branching-Workflows
- 3.5 Remote-Branches
- 3.6 Rebasing
- 3.7 Zusammenfassung
-
4. Git auf dem Server
- 4.1 Die Protokolle
- 4.2 Git auf einem Server einrichten
- 4.3 Generieren Ihres SSH-Public-Keys
- 4.4 Einrichten des Servers
- 4.5 Git Daemon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Drittanbieter-Hosting-Optionen
- 4.10 Zusammenfassung
-
5. Verteiltes Git
-
6. GitHub
-
7. Git-Werkzeuge
- 7.1 Revisionsauswahl
- 7.2 Interaktives Staging
- 7.3 Stashing und Bereinigen
- 7.4 Ihre Arbeit signieren
- 7.5 Suchen
- 7.6 Historie umschreiben
- 7.7 Reset entmystifiziert
- 7.8 Fortgeschrittenes Merging
- 7.9 Rerere
- 7.10 Debugging mit Git
- 7.11 Submodule
- 7.12 Bundling
- 7.13 Ersetzen
- 7.14 Credential-Speicher
- 7.15 Zusammenfassung
-
8. Git anpassen
-
9. Git und andere Systeme
- 9.1 Git als Client
- 9.2 Migration zu Git
- 9.3 Zusammenfassung
-
10. Git-Interna
- 10.1 Plumbing und Porcelain
- 10.2 Git-Objekte
- 10.3 Git-Referenzen
- 10.4 Packfiles
- 10.5 Die Refspec
- 10.6 Übertragungsprotokolle
- 10.7 Wartung und Datenwiederherstellung
- 10.8 Umgebungsvariablen
- 10.9 Zusammenfassung
-
Anhang A: Git in anderen Umgebungen
- A1.1 Grafische Oberflächen
- A1.2 Git in Visual Studio
- A1.3 Git in Visual Studio Code
- A1.4 Git in IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git in Sublime Text
- A1.6 Git in Bash
- A1.7 Git in Zsh
- A1.8 Git in PowerShell
- A1.9 Zusammenfassung
-
Anhang B: Git in Ihre Anwendungen einbetten
- A2.1 Kommandozeilen-Git
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
Anhang C: Git-Befehle
- A3.1 Einrichtung und Konfiguration
- A3.2 Projekte abrufen und erstellen
- A3.3 Grundlegendes Snapshotting
- A3.4 Branching und Merging
- A3.5 Projekte teilen und aktualisieren
- A3.6 Inspektion und Vergleich
- A3.7 Debugging
- A3.8 Patching
- A3.9 E-Mail
- A3.10 Externe Systeme
- A3.11 Administration
- A3.12 Plumbing-Befehle
10.3 Git Internals - Git-Referenzen
Git-Referenzen
Wenn Sie an der Historie Ihres Repositorys interessiert wären, die von einem Commit, sagen wir, 1a410e, erreichbar ist, könnten Sie etwas wie git log 1a410e ausführen, um diese Historie anzuzeigen. Sie müssten sich jedoch immer noch daran erinnern, dass 1a410e der Commit ist, den Sie als Ausgangspunkt für diese Historie verwenden möchten. Stattdessen wäre es einfacher, wenn Sie eine Datei hätten, in der Sie diesen SHA-1-Wert unter einem einfachen Namen speichern könnten, damit Sie diesen einfachen Namen anstelle des rohen SHA-1-Werts verwenden könnten.
In Git werden diese einfachen Namen „Referenzen“ oder „Refs“ genannt; die Dateien, die diese SHA-1-Werte enthalten, finden Sie im Verzeichnis .git/refs. Im aktuellen Projekt enthält dieses Verzeichnis keine Dateien, aber eine einfache Struktur
$ find .git/refs
.git/refs
.git/refs/heads
.git/refs/tags
$ find .git/refs -type f
Um eine neue Referenz zu erstellen, die Ihnen hilft, sich zu merken, wo sich Ihr letzter Commit befindet, können Sie technisch etwas so Einfaches tun wie dieses
$ echo 1a410efbd13591db07496601ebc7a059dd55cfe9 > .git/refs/heads/master
Jetzt können Sie die gerade erstellte HEAD-Referenz anstelle des SHA-1-Werts in Ihren Git-Befehlen verwenden
$ git log --pretty=oneline master
1a410efbd13591db07496601ebc7a059dd55cfe9 Third commit
cac0cab538b970a37ea1e769cbbde608743bc96d Second commit
fdf4fc3344e67ab068f836878b6c4951e3b15f3d First commit
Sie werden nicht dazu angehalten, die Referenzdateien direkt zu bearbeiten. Stattdessen bietet Git den sichereren Befehl git update-ref an, um dies zu tun, wenn Sie eine Referenz aktualisieren möchten
$ git update-ref refs/heads/master 1a410efbd13591db07496601ebc7a059dd55cfe9
Das ist im Grunde das, was ein Branch in Git ist: ein einfacher Zeiger oder eine Referenz auf den Kopf einer Arbeitslinie. Um einen Branch zurück zum zweiten Commit zu erstellen, können Sie dies tun
$ git update-ref refs/heads/test cac0ca
Ihr Branch enthält nur die Arbeit ab diesem Commit
$ git log --pretty=oneline test
cac0cab538b970a37ea1e769cbbde608743bc96d Second commit
fdf4fc3344e67ab068f836878b6c4951e3b15f3d First commit
Nun sieht Ihre Git-Datenbank konzeptionell etwa so aus
Wenn Sie Befehle wie git branch <branch> ausführen, führt Git im Grunde diesen update-ref-Befehl aus, um den SHA-1 des letzten Commits des Branches, auf dem Sie sich befinden, in die gewünschte neue Referenz einzufügen.
Der HEAD
Die Frage ist nun, wenn Sie git branch <branch> ausführen, woher weiß Git den SHA-1 des letzten Commits? Die Antwort ist die HEAD-Datei.
Normalerweise ist die HEAD-Datei eine symbolische Referenz auf den Branch, auf dem Sie sich gerade befinden. Mit symbolischer Referenz meinen wir, dass sie im Gegensatz zu einer normalen Referenz einen Zeiger auf eine andere Referenz enthält.
In einigen seltenen Fällen kann die HEAD-Datei jedoch den SHA-1-Wert eines Git-Objekts enthalten. Dies geschieht, wenn Sie ein Tag, einen Commit oder einen Remote-Branch auschecken, wodurch Ihr Repository in den Zustand "detached HEAD" versetzt wird.
Wenn Sie sich die Datei ansehen, sehen Sie normalerweise etwas wie dieses
$ cat .git/HEAD
ref: refs/heads/master
Wenn Sie git checkout test ausführen, aktualisiert Git die Datei, sodass sie so aussieht
$ cat .git/HEAD
ref: refs/heads/test
Wenn Sie git commit ausführen, erstellt es das Commit-Objekt und gibt als Elternteil dieses Commit-Objekts den SHA-1-Wert an, auf den die Referenz in HEAD zeigt.
Sie können diese Datei auch manuell bearbeiten, aber auch hierfür gibt es einen sichereren Befehl: git symbolic-ref. Sie können den Wert Ihres HEAD mit diesem Befehl lesen
$ git symbolic-ref HEAD
refs/heads/master
Sie können den Wert von HEAD auch mit demselben Befehl festlegen
$ git symbolic-ref HEAD refs/heads/test
$ cat .git/HEAD
ref: refs/heads/test
Sie können keine symbolische Referenz außerhalb des Refs-Stils festlegen
$ git symbolic-ref HEAD test
fatal: Refusing to point HEAD outside of refs/
Tags
Wir haben gerade die drei Hauptobjekttypen von Git (blobs, trees und commits) besprochen, aber es gibt einen vierten. Das Tag-Objekt ist dem Commit-Objekt sehr ähnlich – es enthält einen Tagger, ein Datum, eine Nachricht und einen Zeiger. Der Hauptunterschied besteht darin, dass ein Tag-Objekt im Allgemeinen auf einen Commit und nicht auf einen Tree zeigt. Es ist wie eine Branch-Referenz, aber es bewegt sich nie – es zeigt immer auf denselben Commit, gibt ihm aber einen freundlicheren Namen.
Wie in Git Basics besprochen, gibt es zwei Arten von Tags: annotierte und leichtgewichtige. Sie können einen leichtgewichtigen Tag erstellen, indem Sie etwas wie dieses ausführen
$ git update-ref refs/tags/v1.0 cac0cab538b970a37ea1e769cbbde608743bc96d
Das ist alles, was ein leichtgewichtiger Tag ist – eine Referenz, die sich nie bewegt. Ein annotierter Tag ist jedoch komplexer. Wenn Sie einen annotierten Tag erstellen, erstellt Git ein Tag-Objekt und schreibt dann eine Referenz, die darauf zeigt, anstatt direkt auf den Commit. Dies können Sie sehen, indem Sie einen annotierten Tag erstellen (mit der Option -a)
$ git tag -a v1.1 1a410efbd13591db07496601ebc7a059dd55cfe9 -m 'Test tag'
Hier ist der SHA-1-Wert des erstellten Objekts
$ cat .git/refs/tags/v1.1
9585191f37f7b0fb9444f35a9bf50de191beadc2
Führen Sie nun git cat-file -p auf diesem SHA-1-Wert aus
$ git cat-file -p 9585191f37f7b0fb9444f35a9bf50de191beadc2
object 1a410efbd13591db07496601ebc7a059dd55cfe9
type commit
tag v1.1
tagger Scott Chacon <schacon@gmail.com> Sat May 23 16:48:58 2009 -0700
Test tag
Beachten Sie, dass der Objekt-Eintrag auf den Commit-SHA-1-Wert zeigt, den Sie getaggt haben. Beachten Sie auch, dass er nicht auf einen Commit zeigen muss; Sie können jedes Git-Objekt taggen. Im Quellcode von Git hat der Maintainer beispielsweise seinen öffentlichen GPG-Schlüssel als Blob-Objekt hinzugefügt und ihn dann getaggt. Sie können den öffentlichen Schlüssel anzeigen, indem Sie dies in einem Klon des Git-Repositorys ausführen
$ git cat-file blob junio-gpg-pub
Das Linux-Kernel-Repository hat auch ein Tag-Objekt, das nicht auf einen Commit zeigt – der erste erstellte Tag zeigt auf den initialen Tree des Imports des Quellcodes.
Remotes
Die dritte Art von Referenz, die Sie sehen werden, ist eine Remote-Referenz. Wenn Sie ein Remote hinzufügen und dorthin pushen, speichert Git den Wert, den Sie zuletzt für jeden Branch zu diesem Remote gepusht haben, im Verzeichnis refs/remotes. Sie können beispielsweise ein Remote namens origin hinzufügen und Ihren master-Branch dorthin pushen
$ git remote add origin git@github.com:schacon/simplegit-progit.git
$ git push origin master
Counting objects: 11, done.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (7/7), 716 bytes, done.
Total 7 (delta 2), reused 4 (delta 1)
To git@github.com:schacon/simplegit-progit.git
a11bef0..ca82a6d master -> master
Dann können Sie sehen, was der master-Branch auf dem origin-Remote zuletzt war, als Sie mit dem Server kommuniziert haben, indem Sie die Datei refs/remotes/origin/master überprüfen
$ cat .git/refs/remotes/origin/master
ca82a6dff817ec66f44342007202690a93763949
Remote-Referenzen unterscheiden sich von Branches (refs/heads-Referenzen) hauptsächlich darin, dass sie als schreibgeschützt betrachtet werden. Sie können sie mit git checkout zuordnen, aber Git wird HEAD nicht symbolisch auf sie verweisen, sodass Sie sie nie mit einem commit-Befehl aktualisieren. Git verwaltet sie als Lesezeichen für den letzten bekannten Zustand der Branches auf diesen Servern.