Hallo Habr! Ich präsentiere Ihnen die Übersetzung des Artikels "Git for Computer Scientists" von Tommi Virtanen.
GIT Inside Out: Eine Einführung
Von mir selbst: Ich habe regelmäßig Artikel darüber gelesen, wie verschiedene populäre Technologien unter der Haube angeordnet sind. Ich bin auf dieses Material gestoßen . Der Artikel schien interessant zu sein, da einfache und verständliche Schemata vorhanden waren, die viel besser wahrgenommen werden als Blätter eines langweiligen Textes. Ich beschloss, ins Russische zu übersetzen. Bilder aus dem Original.
Wer wird interessiert und möglicherweise nützlich sein: Leute, die jeden Tag mit Git arbeiten (d. H. Jede Sekunde, wenn nicht der erste Softwareentwickler) und die den Mechanismus seiner Arbeit besser verstehen wollen.
Hinweis: Zum besseren Verständnis des Artikels sollte man sich ein Tier wie einen gerichteten azyklischen Graphen (DAG) vorstellen .
Objektspeicherung
Das Git-Objekt-Repository ist grob gesagt eine DAG, die verschiedene Arten von Objekten enthält. Objekte werden in komprimierter Form gespeichert und durch SHA-1-Hashes identifiziert (dies ist KEIN Hash des Inhalts der Datei, die das Objekt darstellt, sondern seiner Darstellung in Git).
Blob

Blob ist ein einfaches Objekt, nur eine Sammlung von Bytes. Es kann sich um eine Datei, einen symbolischen Link oder was auch immer handeln. Die Semantik wird durch das Objekt bestimmt, das auf diesen Blob zeigt.
Baum

Objekte vom Typ "Baum" beschreiben Verzeichnisse (Verzeichnisse). Sie können auf Blobs verweisen, in denen der Inhalt von Dateien gespeichert ist, sowie auf andere Bäume, wodurch eine Unterverzeichnisstruktur erstellt wird.
Wenn ein Knoten auf einen anderen Knoten in der DAG zeigt, sagen sie, dass dies von diesem Knoten abhängt , d. H. kann ohne es nicht existieren. Knotenpunktknoten können mit der Garbage Collection (Befehl git gc ) gelöscht oder mit dem Befehl git fsck --lost-found wiederhergestellt werden.
Festschreiben

Commit bezieht sich auf einen Baum, der den Status von Dateien in Git zum Zeitpunkt der Erstellung des Commits darstellt. Commit kann sich auch auf andere Commits beziehen, die seine Eltern sind:
- Wenn das Commit mehr als ein übergeordnetes Element hat, bedeutet dies, dass es den Zusammenführungsvorgang beschreibt (Zusammenführen).
- Wenn das Commit keine Eltern hat, ist dies das sogenannte anfängliche (anfängliche) Commit (d. H. Das erste im Repository).
- Es kann auch Fälle geben, in denen mehr als ein anfängliches Commit im Repository vorhanden ist. Dies bedeutet normalerweise, dass zwei separate Repositorys zusammengeführt werden
Der Hauptteil des Festschreibungsobjekts ist eine Festschreibungsnachricht .
Refs (Links)

Links (oder Überschriften oder Zweige) ähneln Aufklebern mit Notizen, die auf DAG-Knoten, einer Art von Notizen oder Lesezeichen eingefügt sind - „Ich arbeite hier“. Im Gegensatz zu DAG-Knoten, die nicht geändert und nur hinzugefügt werden können, können Links nach Belieben verschoben werden. Sie werden nicht im Verlauf gespeichert und nicht direkt zwischen Repositorys übertragen.
Der Befehl git commit fügt der DAG einen neuen Knoten hinzu und verschiebt ein Lesezeichen für den aktuellen Zweig.
Links befinden sich im Namespace Heads / Branchname , aber ein Teil der Heads kann weggelassen werden.
Die HEAD- Verknüpfung unterscheidet sich - sie zeigt nicht auf einen Knoten, sondern auf eine andere Verknüpfung - dies ist ein Zeiger auf den aktuell aktiven Zweig.
Remote-Refs

Dies sind grob gesagt Aufkleber einer anderen Farbe. Der Unterschied besteht darin, dass sich Remoteverbindungen in einem anderen Namespace befinden und auch von einem Remoteserver verwaltet werden. Verwenden Sie zum Aktualisieren den Befehl git fetch .
Tag

Ein Tag ist eine Kombination aus einem DAG-Knoten und einem Aufkleber (eine andere Farbe). Das Tag weist auf das Festschreiben hin und enthält eine optionale Nachricht und eine GPG-Signatur. Ein Aufkleber (Link) ist eine einfache Möglichkeit, auf das Tag zuzugreifen. Im Falle eines Verlusts kann er mit dem Befehl git fsck --lost-found wiederhergestellt werden.
Ein Git-Repository ist also eine Kombination aus DAG und Links.
Die Geschichte
Nachdem wir nun wissen, wie Git den Versionsverlauf speichert, versuchen wir, verschiedene Vorgänge darzustellen und zu verstehen, wie sich Git von Systemen unterscheidet, die den Verlauf als lineare Änderungen für jeden Zweig darstellen.

Das einfachste Repository. Wir haben gerade das Remote-Repository mit einem einzigen Commit kopiert ( Git-Klon ).

Hier haben wir das Remote-Repository gelesen ( git fetch ) und 1 neues Commit erhalten, es aber noch nicht mit unserem Zweig zusammengeführt.

Folgendes passiert nach dem Ausführen des Befehls git merge remotes / MYSERVER / master . Da die Zusammenführung als schneller Vorlauf durchgeführt wurde (in unserem lokalen Zweig gab es keine lokalen Festschreibungen), geschah Folgendes: Die Dateien unserer Arbeitskopie wurden geändert, und der Zeiger auf den Zweig wurde ebenfalls verschoben.

Führen Sie git commit lokal aus und dann git fetch . Jetzt haben wir sowohl lokales als auch Remote-Commit. Natürlich brauchen Sie eine Zusammenführung .

Dies ist das Ergebnis des Befehls git merge remotes / MYSERVER / master . Da wir ein lokales Commit hatten, ist dies kein schneller Vorlauf, und es wird ein separates Commit für die Zusammenführung in der DAG erstellt. Hinweis - Er hat 2 Eltern festgeschrieben.

So sieht unser Baum nach mehreren Commits in beiden Zweigen (lokal und remote) + Merge aus. Sie können deutlich sehen, wie Git DAG die gesamte Geschichte unserer Aktionen erfasst.

Eine solche Geschichte ist jedoch schwer zu lesen. Wenn Sie Ihre Niederlassung noch nicht veröffentlicht haben oder mit anderen Teammitgliedern vereinbart haben, dass sie in ihrer Arbeit nicht darauf aufbauen sollten, haben Sie eine Alternative: Sie können eine Basis für Ihre Niederlassung erstellen . In diesem Fall wird Ihr Commit durch ein anderes Commit mit einem anderen übergeordneten Commit ersetzt, zu dem auch der Link zum Zweig verschoben wird.
In diesem Fall bleiben Ihre alten Commits bis zur Garbage Collection in der DAG. Im Prinzip ist dies eine Art Versicherung für den Fall, dass etwas schief geht. Wenn Sie noch Links zu alten Commits haben, werden diese gespeichert, solange die Links vorhanden sind.
Sie sollten NICHT auf Zweige zurückgreifen, auf denen andere Personen ein Commit erstellt haben. Sie können sie wiederherstellen (und nicht einmal sehr schwierig), aber dies führt zu Verwirrung und viel nutzloser Arbeit.

Hier erfahren Sie, wie die Garbage Collection (oder das Ignorieren unzugänglicher Commits) und das Erstellen eines neuen Commits über dem Zweig, auf den die Rebase angewendet wurde, aussehen.

Mit Rebase können Sie auch mehrere Commits gleichzeitig verschieben.
Das ist alles. Ich hoffe, das Material wird nützlich sein.