Git

Aus besserwiki.de
Git
Git-logo-2012.svg
Git session.svg
Eine Befehlszeilensitzung, die die Erstellung eines Repositorys, das Hinzufügen einer Datei und die Remote-Synchronisierung zeigt
Ursprüngliche(r) Autor(en)Linus Torvalds
Entwickler(n)Junio Hamano und andere
Erste Veröffentlichung7. April 2005; vor 17 Jahren
Geschrieben inHauptsächlich in C, mit GUI und Programmierskripten in Shell-Skript, Perl, Tcl und Python geschrieben
BetriebssystemPOSIX (Linux, macOS, Solaris, AIX), Windows
Verfügbar inEnglisch
TypVersionskontrolle
LizenzGPL-2.0-only

Git (/ɡɪt/) ist eine Software zur Nachverfolgung von Änderungen an beliebigen Dateien, die in der Regel zur Koordinierung der Arbeit von Programmierern verwendet wird, die während der Software-Entwicklung gemeinsam an Quellcode arbeiten. Zu seinen Zielen gehören Geschwindigkeit, Datenintegrität und Unterstützung für verteilte, nicht-lineare Arbeitsabläufe (Tausende von parallelen Zweigen auf verschiedenen Systemen).

Git wurde ursprünglich von Linus Torvalds im Jahr 2005 für die Entwicklung des Linux-Kernels entwickelt, wobei andere Kernel-Entwickler zu seiner anfänglichen Entwicklung beitrugen. Seit 2005 ist Junio Hamano der Hauptverantwortliche. Wie bei den meisten anderen verteilten Versionskontrollsystemen und im Gegensatz zu den meisten Client-Server-Systemen ist jedes Git-Verzeichnis auf jedem Computer ein vollwertiges Repository mit vollständiger Historie und vollständigen Versionsverfolgungsfunktionen, unabhängig vom Netzwerkzugang oder einem zentralen Server. Git ist eine freie und quelloffene Software, die nur unter der GPL-2.0-Lizenz vertrieben wird.

Geschichte

Durch eine Lizenzänderung des bis dahin genutzten proprietären BitKeeper-Systems konnten die Linux-Kernel-Entwickler dieses nicht mehr kostenlos verwenden und somit blieb vielen Entwicklern der Zugang verwehrt. Daher begann Torvalds im April 2005 mit der Entwicklung einer neuen Quellcode-Management-Software und präsentierte bereits wenige Tage nach deren Ankündigung eine erste Version.

Altes Logo

Torvalds wünschte sich ein verteiltes System, das wie BitKeeper genutzt werden kann und die folgenden Anforderungen erfüllt:

  1. Unterstützung verteilter, BitKeeper-ähnlicher Arbeitsabläufe
  2. Sehr hohe Sicherheit gegen sowohl unbeabsichtigte als auch böswillige Verfälschung
  3. Hohe Effizienz

Ein bereits existierendes Projekt namens Monotone entsprach den ersten beiden Anforderungen, das dritte Kriterium wurde jedoch von keinem bestehenden System erfüllt.

Torvalds entschied sich dagegen, Monotone an seine Anforderungen anzupassen und begann stattdessen, ein eigenes System zu entwickeln. Einer der Hauptgründe für diesen Schritt war die Arbeitsweise, für die Monotone nach Torvalds Ansicht optimiert ist. Torvalds argumentierte, dass einzelne Revisionen von einem anderen Entwickler in den eigenen Entwicklungszweig zu importieren zu Rosinenpickerei und unordentlichen Repositorien führen würde. Wenn hingegen immer ganze Zweige importiert werden, wären Entwickler gezwungen, diese aufzuräumen. Dazu sei es notwendig, auch die Möglichkeit von Wegwerf-Zweigen anzubieten.

“This is my only real conceptual gripe with ‘monotone’. I like the model, but they make it much harder than it should be to have throw-away trees due to the fact that they seem to be working on the assumption of ‘one database per developer’ rather than ‘one database per tree’. You don’t have to follow that model, but it seems to be what the setup is geared for, and together with their ‘branches’ it means that I think a monotone database easily gets very cruddy. The other problem with monotone is just performance right now, but that’s hopefully not too fundamental.”

„Ich habe nur ein wirkliches konzeptionelles Problem mit ‚monotone‘: Ich mag die Arbeitsweise, aber sie erschwert die Nutzung von Wegwerf-Bäumen, weil das Konzept anscheinend auf der Annahme ‚eine Datenbank je Entwickler‘ statt ‚eine Datenbank je Baum‘ basiert. Man braucht zwar nicht diesem Modell zu folgen, aber die System-Einrichtung scheint darauf ausgerichtet zu sein. Zusammen mit ihren ‚Zweigen‘ befürchte ich ein schnelles Verdrecken der monotone-Datenbank. Ein anderes, hoffentlich nicht zu grundlegendes Problem, ist die derzeitige Leistungsfähigkeit von monotone.“

Linus Torvalds

Gits Gestaltung verwendet einige Ideen aus Monotone sowie BitKeeper, aber keinen Quellcode daraus. Es sollte ausdrücklich ein eigenständiges Versionsverwaltungssystem sein.

Derzeitiger Maintainer von Git ist Junio Hamano.

Die Entwicklung von Git begann im April 2005, nachdem viele Entwickler des Linux-Kernels den Zugriff auf BitKeeper aufgegeben hatten, ein proprietäres System zur Verwaltung der Versionskontrolle (SCM), das sie seit 2002 zur Pflege des Projekts verwendet hatten. Der Urheberrechtsinhaber von BitKeeper, Larry McVoy, hatte die kostenlose Nutzung des Produkts zurückgezogen, nachdem er behauptet hatte, Andrew Tridgell habe SourcePuller durch Reverse Engineering der BitKeeper-Protokolle entwickelt. Der gleiche Vorfall war auch der Auslöser für die Entwicklung eines anderen Versionskontrollsystems, Mercurial.

Diese Kriterien schlossen jedes damals verwendete Versionskontrollsystem aus, so dass Torvalds unmittelbar nach der Veröffentlichung des Linux-Kernels 2.6.12-rc2 begann, sein eigenes zu schreiben.

Die Entwicklung von Git begann am 3. April 2005. Torvalds kündigte das Projekt am 6. April an, und am nächsten Tag wurde es selbst gehostet. Die erste Zusammenführung mehrerer Zweige fand am 18. April statt. Torvalds erreichte seine Leistungsziele; am 29. April wurde das im Entstehen begriffene Git beim Aufzeichnen von Patches für den Linux-Kernelbaum mit einer Rate von 6,7 Patches pro Sekunde gemessen. Am 16. Juni verwaltete Git die Veröffentlichung des Kernels 2.6.12.

Namensgebung

Torvalds machte einen sarkastischen Witz über den Namen git (was in der englischen Umgangssprache "unpleasant person" bedeutet): "Ich bin ein egoistischer Bastard und benenne alle meine Projekte nach mir selbst. Erst 'Linux', jetzt 'git'." Die Manpage beschreibt Git als "the stupid content tracker". Die Read-me-Datei des Quellcodes führt das weiter aus:

"git" kann alles Mögliche bedeuten, je nach Laune.

  • Eine zufällige Kombination aus drei Buchstaben, die aussprechbar ist und eigentlich von keinem gängigen UNIX-Befehl verwendet wird. Die Tatsache, dass es sich um eine falsche Aussprache von "get" handelt, mag relevant sein oder auch nicht.
  • Dumm. Verächtlich und verachtenswert. Einfach. Suchen Sie sich etwas aus dem Wörterbuch der Umgangssprache aus.
  • "Global Information Tracker": Sie haben gute Laune, und es funktioniert tatsächlich für Sie. Engel singen, und ein Licht erfüllt plötzlich den Raum.
  • "Gottverdammter, idiotischer Haufen Scheiße": wenn es kaputt geht.

Im Quellcode von Git wird das Programm als "der Informationsmanager aus der Hölle" bezeichnet.

Veröffentlichungen

Liste der Git-Versionen:

Version Ursprüngliches Veröffentlichungsdatum Letzte (gepatchte) Version Veröffentlichungsdatum (des Patches) Bemerkenswerte Änderungen
0.99 2005-07-11 0.99.9n 2005-12-15
1.0 2005-12-21 1.0.13 2006-01-27
1.1 2006-01-08 1.1.6 2006-01-30
1.2 2006-02-12 1.2.6 2006-04-08
1.3 2006-04-18 1.3.3 2006-05-16
1.4 2006-06-10 1.4.4.5 2008-07-16
1.5 2007-02-14 1.5.6.6 2008-12-17
1.6 2008-08-17 1.6.6.3 2010-12-15
1.7 2010-02-13 1.7.12.4 2012-10-17
1.8 2012-10-21 1.8.5.6 2014-12-17
1.9 2014-02-14 1.9.5 2014-12-17
2.0 2014-05-28 2.0.5 2014-12-17
2.1 2014-08-16 2.1.4 2014-12-17
2.2 2014-11-26 2.2.3 2015-09-04
2.3 2015-02-05 2.3.10 2015-09-29
2.4 2015-04-30 2.4.12 2017-05-05
2.5 2015-07-27 2.5.6 2017-05-05
2.6 2015-09-28 2.6.7 2017-05-05
2.7 2015-10-04 2.7.6 2017-07-30
2.8 2016-03-28 2.8.6 2017-07-30
2.9 2016-06-13 2.9.5 2017-07-30
2.10 2016-09-02 2.10.5 2017-09-22
2.11 2016-11-29 2.11.4 2017-09-22
2.12 2017-02-24 2.12.5 2017-09-22
2.13 2017-05-10 2.13.7 2018-05-22
2.14 2017-08-04 2.14.6 2019-12-07
2.15 2017-10-30 2.15.4 2019-12-07
2.16 2018-01-17 2.16.6 2019-12-07
2.17 2018-04-02 2.17.6 2021-03-09
2.18 2018-06-21 2.18.5 2021-03-09
2.19 2018-09-10 2.19.6 2021-03-09
2.20 2018-12-09 2.20.5 2021-03-09
2.21 2019-02-24 2.21.4 2021-03-09
2.22 2019-06-07 2.22.5 2021-03-09
2.23 2019-08-16 2.23.4 2021-03-09
2.24 2019-11-04 2.24.4 2021-03-09
2.25 2020-01-13 2.25.5 2021-03-09 Spärliche Checkout-Verwaltung leicht gemacht
2.26 2020-03-22 2.26.3 2021-03-09
  • Protokollversion 2 ist jetzt die Standardversion
  • Einige neue Konfigurationstricks
  • Aktualisierungen für git sparse-checkout
2.27 2020-06-01 2.27.1 2021-03-09
2.28 2020-07-27 2.28.1 2021-03-09
  • Einführung von init.defaultBranch
  • Bloom-Filter mit geändertem Pfad
2.29 2020-10-19 2.29.3 2021-03-09
  • Experimentelle SHA-256-Unterstützung
  • Negative refspecs
  • Neue Git-Shortlog-Tricks
2.30 2020-12-27 2.30.4 2022-04-13
  • Userdiff für PHP-Update, Rust, CSS-Update
  • Das Skript zur Befehlszeilenvervollständigung (in contrib/) hat gelernt, dass "git stash show" die Optionen von "git diff" übernimmt.
2.31 2021-03-15 2.31.3 2022-04-13
  • git difftool fügt die Option --skip-to hinzu
  • --format Erweiterungen für maschinenlesbare
  • git pull warning zur Angabe von rebase oder merge
2.32 2021-06-06 2.32.2 2022-04-13
2.33 2021-08-16 2.33.3 2022-04-13
2.34 2021-11-15 2.34.3 2022-04-13
2.35 2022-01-25 2.35.3 2022-04-13
2.36 2022-04-18 2.36.1 2022-05-09
2.37 2022-06-27 2.37.0
Legende:
Alte Version
Ältere Version, die noch gepflegt wird
Neueste Version
Quellen:

Gestaltung

Das Design von Git wurde von BitKeeper und Monotone inspiriert. Ursprünglich war Git als Low-Level-Versionskontrollsystem konzipiert, auf das andere Frontends wie Cogito oder StGIT aufsetzen konnten. Das Kernprojekt Git hat sich inzwischen zu einem vollständigen Versionskontrollsystem entwickelt, das direkt genutzt werden kann. Obwohl stark von BitKeeper beeinflusst, vermied Torvalds absichtlich konventionelle Ansätze, was zu einem einzigartigen Design führte.

Merkmale

Das Design von Git ist eine Synthese aus Torvalds' Erfahrungen mit Linux bei der Verwaltung eines großen verteilten Entwicklungsprojekts, seinen intimen Kenntnissen über die Leistung von Dateisystemen aus demselben Projekt und der dringenden Notwendigkeit, in kurzer Zeit ein funktionierendes System zu entwickeln. Diese Einflüsse führten zu den folgenden Implementierungsentscheidungen:

Starke Unterstützung für nicht-lineare Entwicklung
Git unterstützt schnelle Verzweigungen und Zusammenführungen und enthält spezielle Werkzeuge zur Visualisierung und Navigation eines nicht-linearen Entwicklungsverlaufs. In Git wird davon ausgegangen, dass eine Änderung öfter zusammengeführt wird, als sie geschrieben wird, da sie an verschiedene Prüfer weitergegeben wird. In Git sind Zweige sehr leichtgewichtig: Ein Zweig ist nur ein Verweis auf einen Commit. Mit seinen Eltern-Commits kann die gesamte Zweigstruktur aufgebaut werden.
Verteilte Entwicklung
Wie Darcs, BitKeeper, Mercurial, Bazaar und Monotone bietet Git jedem Entwickler eine lokale Kopie des gesamten Entwicklungsverlaufs, und Änderungen werden von einem solchen Repository in ein anderes kopiert. Diese Änderungen werden als hinzugefügte Entwicklungszweige importiert und können auf die gleiche Weise zusammengeführt werden wie ein lokal entwickelter Zweig.
Kompatibilität mit bestehenden Systemen und Protokollen
Repositories können über das Hypertext Transfer Protocol (HTTP), das File Transfer Protocol (FTP) oder ein Git-Protokoll entweder über einen einfachen Socket oder Secure Shell (ssh) veröffentlicht werden. Git verfügt auch über eine CVS-Server-Emulation, die die Verwendung bestehender CVS-Clients und IDE-Plugins für den Zugriff auf Git-Repositories ermöglicht. Subversion-Repositorys können direkt mit git-svn verwendet werden.
Effizienter Umgang mit großen Projekten
Torvalds hat Git als sehr schnell und skalierbar beschrieben, und Leistungstests von Mozilla haben gezeigt, dass es beim Diffing großer Repositories um eine Größenordnung schneller ist als Mercurial und GNU Bazaar; das Abrufen der Versionshistorie aus einem lokal gespeicherten Repository kann hundertmal schneller sein als das Abrufen von einem entfernten Server.
Kryptografische Authentifizierung der Historie
Die Git-Historie wird so gespeichert, dass die ID einer bestimmten Version (ein Commit im Sinne von Git) von der gesamten Entwicklungsgeschichte abhängt, die zu diesem Commit geführt hat. Nach der Veröffentlichung ist es nicht mehr möglich, die alten Versionen zu ändern, ohne dass dies bemerkt wird. Die Struktur ähnelt einem Merkle-Baum, jedoch mit zusätzlichen Daten an den Knoten und Blättern. (Mercurial und Monotone haben ebenfalls diese Eigenschaft).
Toolkit-basierter Entwurf
Git wurde als eine Reihe von in C geschriebenen Programmen und mehreren Shell-Skripten entwickelt, die Wrapper für diese Programme darstellen. Obwohl die meisten dieser Skripte aus Geschwindigkeits- und Portabilitätsgründen inzwischen in C umgeschrieben wurden, ist das Design erhalten geblieben, und es ist einfach, die Komponenten miteinander zu verknüpfen.
Einsteckbare Merge-Strategien
Als Teil des Toolkits verfügt Git über ein klar definiertes Modell für eine unvollständige Zusammenführung und über mehrere Algorithmen für die Vervollständigung, die darin gipfeln, dass dem Benutzer mitgeteilt wird, dass die Zusammenführung nicht automatisch abgeschlossen werden kann und eine manuelle Bearbeitung erforderlich ist.
Müll sammelt sich an, bis er eingesammelt wird
Der Abbruch von Operationen oder das Zurückziehen von Änderungen hinterlässt nutzlos herumliegende Objekte in der Datenbank. Dabei handelt es sich in der Regel nur um einen kleinen Teil der ständig wachsenden Anzahl der gewünschten Objekte. Git führt automatisch eine Garbage Collection durch, wenn genügend lose Objekte im Repository erstellt wurden. Die Garbage Collection kann explizit mit git gc aufgerufen werden.
Regelmäßiges explizites Packen von Objekten
Git speichert jedes neu erstellte Objekt in einer eigenen Datei. Dies ist zwar individuell komprimiert, nimmt aber sehr viel Platz in Anspruch und ist ineffizient. Dies wird durch die Verwendung von Packs gelöst, die eine große Anzahl von Objekten delta-komprimiert in einer Datei (oder einem Netzwerk-Byte-Stream) namens Packfile speichern. Bei der Komprimierung von Packs wird die Heuristik verwendet, dass Dateien mit demselben Namen wahrscheinlich ähnlich sind, ohne dass dies für die Korrektheit ausschlaggebend ist. Für jede Packdatei wird eine entsprechende Indexdatei erstellt, die den Offset jedes Objekts in der Packdatei angibt. Neu erstellte Objekte (mit neu hinzugefügter Historie) werden nach wie vor als einzelne Objekte gespeichert, so dass ein regelmäßiges Umpacken erforderlich ist, um den Platzbedarf zu verringern. Der Prozess des Packens des Repositorys kann sehr rechenintensiv sein. Indem Git zulässt, dass Objekte in einem losen, aber schnell erzeugten Format im Repository vorhanden sind, kann der kostspielige Packvorgang auf einen späteren Zeitpunkt verschoben werden, wenn die Zeit weniger wichtig ist, z. B. auf das Ende eines Arbeitstages. Git führt ein regelmäßiges Umpacken automatisch durch, aber auch ein manuelles Umpacken ist mit dem Befehl git gc möglich. Um die Datenintegrität zu gewährleisten, sind sowohl die Packdatei als auch ihr Index mit einer SHA-1-Prüfsumme versehen, und auch der Dateiname der Packdatei enthält eine SHA-1-Prüfsumme. Um die Integrität eines Repositorys zu überprüfen, führen Sie den Befehl git fsck aus.

Eine weitere Eigenschaft von Git ist die Erstellung von Momentaufnahmen von Verzeichnisbäumen mit Dateien. Die ersten Systeme zur Verfolgung von Quellcodeversionen, das Source Code Control System (SCCS) und das Revision Control System (RCS), arbeiteten mit einzelnen Dateien und betonten die Platzersparnis, die sich durch verschachtelte Deltas (SCCS) oder Delta-Codierung (RCS) der (meist ähnlichen) Versionen ergab. Spätere Revisionskontrollsysteme hielten an dieser Vorstellung fest, dass eine Datei über mehrere Revisionen eines Projekts hinweg eine Identität hat. Torvalds lehnte dieses Konzept jedoch ab. Folglich zeichnet Git die Revisionsbeziehungen zwischen Dateien auf keiner Ebene unterhalb des Quellcodebaums explizit auf.

Diese impliziten Revisionsbeziehungen haben einige bedeutende Konsequenzen:

  • Es ist etwas aufwändiger, den Änderungsverlauf einer Datei zu untersuchen als den des gesamten Projekts. Um eine Historie der Änderungen zu erhalten, die eine bestimmte Datei betreffen, muss Git die globale Historie durchgehen und dann feststellen, ob jede Änderung diese Datei verändert hat. Mit dieser Methode der Verlaufsprüfung kann Git jedoch mit gleicher Effizienz einen einzelnen Verlauf erstellen, der die Änderungen an einer beliebigen Gruppe von Dateien zeigt. Ein Unterverzeichnis des Quellcode-Baums und eine zugehörige globale Header-Datei sind zum Beispiel ein sehr häufiger Fall.
  • Umbenennungen werden nicht explizit, sondern implizit behandelt. Eine häufige Beschwerde über CVS ist, dass es den Namen einer Datei benutzt, um ihre Revisionshistorie zu identifizieren, so dass es nicht möglich ist, eine Datei zu verschieben oder umzubenennen, ohne entweder ihre Historie zu unterbrechen oder die Historie umzubenennen und dadurch die Historie ungenau zu machen. Die meisten Post-CVS-Revisionskontrollsysteme lösen dieses Problem, indem sie einer Datei einen eindeutigen, langlebigen Namen geben (analog zu einer Inode-Nummer), der die Umbenennung überdauert. Git zeichnet eine solche Kennung nicht auf, was als Vorteil angeführt wird. Quellcodedateien werden manchmal geteilt oder zusammengeführt oder einfach umbenannt, und dies als einfache Umbenennung aufzuzeichnen, würde eine ungenaue Beschreibung dessen, was in der (unveränderlichen) Historie passiert ist, einfrieren. Git geht dieses Problem an, indem es Umbenennungen beim Durchsuchen des Verlaufs von Schnappschüssen erkennt, anstatt sie beim Erstellen des Schnappschusses aufzuzeichnen. (Kurz gesagt: Bei einer Datei in Revision N ist eine gleichnamige Datei in Revision N - 1 ihr Standardvorfahr. Wenn es jedoch keine gleichnamige Datei in Revision N - 1 gibt, sucht Git nach einer Datei, die nur in Revision N - 1 existierte und der neuen Datei sehr ähnlich ist.) Allerdings erfordert dies bei jeder Überprüfung der Historie mehr CPU-Arbeit, und es stehen mehrere Optionen zur Anpassung der Heuristik zur Verfügung. Dieser Mechanismus funktioniert nicht immer; manchmal wird eine Datei, die mit Änderungen in der gleichen Übertragung umbenannt wird, als Löschung der alten Datei und Erstellung einer neuen Datei gelesen. Entwickler können diese Einschränkung umgehen, indem sie die Umbenennung und die Änderungen getrennt übertragen.

Git implementiert mehrere Zusammenführungsstrategien; eine andere als die Standardstrategie kann zur Zeit der Zusammenführung ausgewählt werden:

  • resolve: der traditionelle Drei-Wege-Zusammenführungsalgorithmus.
  • rekursiv: Dies ist die Standardeinstellung, wenn ein Zweig gezogen oder zusammengeführt wird, und ist eine Variante des Drei-Wege-Zusammenführungsalgorithmus.

    Wenn es mehr als einen gemeinsamen Vorfahren gibt, der für eine dreifache Verschmelzung verwendet werden kann, wird ein verschmolzener Baum mit den gemeinsamen Vorfahren erstellt und dieser als Referenzbaum für die dreifache Verschmelzung verwendet. Tests mit früheren Merge-Commits aus der Entwicklungsgeschichte des Linux 2.6-Kernels haben gezeigt, dass dies zu weniger Merge-Konflikten führt, ohne Fehlmerges zu verursachen. Außerdem können so Zusammenführungen mit Umbenennungen erkannt und behandelt werden.

    - Linus Torvalds
  • Oktopus: Dies ist die Standardeinstellung, wenn mehr als zwei Köpfe zusammengeführt werden.
Dezentrale Verwaltung des gesamten Repositories mit Hilfe von Git

Jeder Benutzer besitzt eine lokale Kopie des gesamten Repositorys, inklusive der Versionsgeschichte (history). So können die meisten Aktionen lokal und ohne Netzwerkzugriff ausgeführt werden. Es wird nicht zwischen lokalen Entwicklungszweigen und Entwicklungszweigen entfernter Repositorien unterschieden. Obwohl es keinen technischen Unterschied zwischen verschiedenen Repositorien gibt (außer dem zwischen normalen und bare-Repositories auf Servern, bei denen kein Working-Tree, also die echten Dateien existiert), gilt die Kopie, auf die von einer Projekt-Homepage aus verwiesen wird, häufig als das offizielle Repositorium, in das die Revisionen der Entwickler übertragen werden. Es existieren spezielle Remote-tracking branches. Das sind Referenzen (siehe Nicht-lineare Entwicklung), die auf den Stand eines anderen Repositoriums zeigen.

Datenstrukturen

Die Primitive von Git sind nicht von Natur aus ein Quellcode-Verwaltungssystem. Torvalds erklärt:

In vielerlei Hinsicht kann man Git einfach als Dateisystem sehen - es ist inhaltsadressierbar und hat eine Vorstellung von Versionierung, aber ich habe es wirklich aus der Sicht eines Dateisystemmenschen entwickelt (hey, Kernel sind mein Metier), und ich habe eigentlich absolut kein Interesse daran, ein traditionelles SCM-System zu entwickeln.

Ausgehend von diesem anfänglichen Entwurfsansatz hat Git alle Funktionen entwickelt, die man von einem traditionellen SCM erwartet, wobei die meisten Funktionen nach Bedarf erstellt und dann im Laufe der Zeit verfeinert und erweitert wurden.

Einige Datenflüsse und Speicherebenen im Git Revisionskontrollsystem

Git verfügt über zwei Datenstrukturen: einen veränderbaren Index (auch Stage oder Cache genannt), der Informationen über das Arbeitsverzeichnis und die nächste zu übertragende Revision zwischenspeichert, und eine unveränderliche Objektdatenbank, die nur Anhänge enthält.

Der Index dient als Verbindungspunkt zwischen der Objektdatenbank und dem Arbeitsbaum.

Die Objektdatenbank enthält fünf Arten von Objekten:

  • Ein Blob (binary large object) ist der Inhalt einer Datei. Blobs haben keinen eigenen Dateinamen, Zeitstempel oder andere Metadaten (der Name eines Blobs ist intern ein Hash des Inhalts). In Git ist jeder Blob eine Version einer Datei, er enthält die Daten der Datei.
  • Ein Baumobjekt ist das Äquivalent eines Verzeichnisses. Es enthält eine Liste von Dateinamen, jeder mit einigen Typbits und einem Verweis auf einen Blob oder ein Baumobjekt, das den Inhalt dieser Datei, des symbolischen Links oder des Verzeichnisses darstellt. Diese Objekte stellen einen Schnappschuss des Quellbaums dar (insgesamt handelt es sich dabei um einen Merkle-Baum, was bedeutet, dass nur ein einziger Hash für den Wurzelbaum ausreicht und in Commits tatsächlich verwendet wird, um den genauen Zustand ganzer Baumstrukturen aus einer beliebigen Anzahl von Unterverzeichnissen und Dateien genau zu bestimmen).
  • Ein Commit-Objekt verknüpft Baumobjekte zu einer Historie. Es enthält den Namen eines Baumobjekts (des obersten Quellverzeichnisses), einen Zeitstempel, eine Protokollnachricht und die Namen von null oder mehr übergeordneten Commit-Objekten.
  • Ein Tag-Objekt ist ein Container, der einen Verweis auf ein anderes Objekt enthält und zusätzliche Metadaten zu einem anderen Objekt enthalten kann. Meistens wird es verwendet, um eine digitale Signatur eines Commit-Objekts zu speichern, das einer bestimmten Version der von Git verfolgten Daten entspricht.
  • Ein Packfile-Objekt ist eine zlib-Version, die aus verschiedenen anderen Objekten komprimiert wurde, um kompakt zu sein und den Transport über Netzwerkprotokolle zu erleichtern.

Jedes Objekt wird durch einen SHA-1-Hash seines Inhalts identifiziert. Git berechnet den Hash und verwendet diesen Wert für den Namen des Objekts. Das Objekt wird in einem Verzeichnis abgelegt, das den ersten beiden Zeichen des Hash entspricht. Der Rest des Hashwerts wird als Dateiname für dieses Objekt verwendet.

Git speichert jede Revision einer Datei als eindeutigen Blob. Die Beziehungen zwischen den Blobs können durch die Untersuchung des Baums und der Commit-Objekte ermittelt werden. Neu hinzugefügte Objekte werden mit Hilfe der zlib-Komprimierung in ihrer Gesamtheit gespeichert. Dies kann schnell eine große Menge an Festplattenspeicherplatz verbrauchen. Daher können Objekte zu Paketen zusammengefasst werden, die eine Delta-Komprimierung verwenden, um Platz zu sparen, und Blobs als ihre Änderungen relativ zu anderen Blobs speichern.

Darüber hinaus speichert Git Etiketten, die Refs (kurz für Referenzen) genannt werden, um die Positionen der verschiedenen Übertragungen anzugeben. Sie werden in der Referenzdatenbank gespeichert und lauten wie folgt:

  • Heads (Zweige): Benannte Referenzen, die automatisch zum neuen Commit weitergereicht werden, wenn ein Commit über ihnen gemacht wird.
  • HEAD: Ein reservierter Kopf, der mit dem Arbeitsbaum verglichen wird, um einen Commit zu erstellen.
  • Tags: Wie Zweigreferenzen, aber an einen bestimmten Commit gebunden. Sie werden verwendet, um wichtige Punkte in der Historie zu kennzeichnen.

Implementierungen

gitg ist ein grafisches Front-End, das GTK+ verwendet.

Git (die Hauptimplementierung in C) wurde in erster Linie für Linux entwickelt, obwohl es auch die meisten anderen Betriebssysteme unterstützt, darunter die BSDs (DragonFly BSD, FreeBSD, NetBSD und OpenBSD), Solaris, macOS und Windows.

Die erste Windows-Portierung von Git war in erster Linie ein Linux-Emulations-Framework, das die Linux-Version hostet. Die Installation von Git unter Windows erzeugt ein ähnlich benanntes Verzeichnis "Program Files", das die Mingw-w64-Portierung der GNU Compiler Collection, Perl 5, MSYS2 (selbst ein Fork von Cygwin, einer Unix-ähnlichen Emulationsumgebung für Windows) und verschiedene andere Windows-Portierungen oder Emulationen von Linux-Dienstprogrammen und -Bibliotheken enthält. Derzeit werden native Windows-Builds von Git als 32- und 64-Bit-Installationsprogramme verteilt. Auf der offiziellen Git-Website wird derzeit ein Git-Build für Windows verwaltet, das noch immer die MSYS2-Umgebung verwendet.

Die JGit-Implementierung von Git ist eine reine Java-Softwarebibliothek, die in jede Java-Anwendung eingebettet werden kann. JGit wird in dem Code-Review-Tool Gerrit und in EGit, einem Git-Client für die Eclipse-IDE, verwendet.

Go-git ist eine Open-Source-Implementierung von Git, die in reinem Go geschrieben ist. Sie wird derzeit zur Unterstützung von Projekten als SQL-Schnittstelle für Git-Code-Repositories und zur Verschlüsselung von Git verwendet.

Die Dulwich-Implementierung von Git ist eine reine Python-Softwarekomponente für Python 2.7, 3.4 und 3.5.

Die libgit2-Implementierung von Git ist eine ANSI-C-Softwarebibliothek ohne weitere Abhängigkeiten, die auf mehreren Plattformen, darunter Windows, Linux, macOS und BSD, eingesetzt werden kann. Sie verfügt über Bindungen für viele Programmiersprachen, darunter Ruby, Python und Haskell.

JS-Git ist eine JavaScript-Implementierung einer Teilmenge von Git.

Git-Server

Daten können neben dem Übertragen auf Dateisystemebene (file://) mit unterschiedlichen Netzwerkprotokollen zwischen Repositories übertragen werden. Git hat ein eigenes, sehr effizientes Protokoll, das den TCP-Port 9418 nutzt (git://), welcher allerdings nur zum Fetchen und Clonen genutzt werden kann, also dem Lesen eines Repositorys. Ebenso kann der Transfer über SSH (ssh://, das gängigste Protokoll für Schreiboperationen), HTTP (http://), HTTPS (https://) oder über (weniger effizient) FTP (ftp://) oder rsync (rsync://) erfolgen. Die Übertragung in das offizielle Repository eines Projekts erfolgt häufig in Form von Patches, die via E-Mail an den Entwickler oder eine Entwicklungs-Mailing-Liste geschickt werden. Alternativ kann auch ein Review-System wie Gerrit verwendet werden. Für Projekte, die auf Websites wie GitHub oder Bitbucket gespeichert ("hosting") werden, kann eine Änderung einfach durch das Pushen eines Branches vorgeschlagen werden, der dann bei Bedarf durch ein Merge in das Projekt integriert wird.

Screenshot der Gitweb-Oberfläche mit einem Commit-Diff

Offene Quelle

  • Hosting des Git-Servers mit dem Git Binary.
  • Gerrit, ein Git-Server, der so konfiguriert werden kann, dass er Code-Reviews unterstützt und Zugriff über ssh, einen integrierten Apache MINA oder OpenSSH oder einen integrierten Jetty-Webserver bietet. Gerrit bietet Integration für LDAP, Active Directory, OpenID, OAuth, Kerberos/GSSAPI, X509 https Client-Zertifikate. Mit Gerrit 3.0 werden alle Konfigurationen als Git-Repositories gespeichert, eine Datenbank ist nicht mehr erforderlich. Gerrit hat eine Pull-Request-Funktion in seinem Kern implementiert, aber es fehlt eine GUI dafür.
  • Phabricator, ein Spin-off von Facebook. Da Facebook hauptsächlich Mercurial verwendet, ist die Git-Unterstützung nicht so ausgeprägt.
  • RhodeCode Community Edition (CE), unterstützt Git, Mercurial und Subversion mit einer AGPLv3-Lizenz.
  • Kallithea, unterstützt sowohl Git als auch Mercurial, entwickelt in Python mit GPL-Lizenz.
  • Externe Projekte wie gitolite, die Skripte auf der Git-Software bereitstellen, um eine feinkörnige Zugriffskontrolle zu ermöglichen.
  • Es gibt mehrere andere FLOSS-Lösungen für das Self-Hosting, darunter Gogs und Gitea, eine Abspaltung von Gogs, die beide in der Sprache Go mit MIT-Lizenz entwickelt wurden.

Git-Server als Dienstleistung

Es gibt viele Angebote von Git-Repositories als Dienst. Zu den bekanntesten gehören GitHub, SourceForge, Bitbucket und GitLab.

Akzeptanz

Die Eclipse Foundation berichtete in ihrer jährlichen Umfrage in der Community, dass Git im Mai 2014 das am weitesten verbreitete Tool zur Quellcodeverwaltung war. 42,9 % der professionellen Softwareentwickler gaben an, Git als primäres Quellcodekontrollsystem zu verwenden, verglichen mit 36,3 % im Jahr 2013 und 32 % im Jahr 2012; oder für Git-Antworten ohne die Verwendung von GitHub: 33,3 % im Jahr 2014, 30,3 % im Jahr 2013, 27,6 % im Jahr 2012 und 12,8 % im Jahr 2011. Das Open-Source-Verzeichnis Black Duck Open Hub berichtet von einer ähnlichen Zunahme bei Open-Source-Projekten.

Stack Overflow hat die Versionskontrolle 2015 (16.694 Antworten), 2017 (30.730 Antworten), 2018 (74.298 Antworten) und 2022 (71.379 Antworten) in seine jährliche Entwicklerumfrage aufgenommen. Git war in diesen Umfragen der überwältigende Favorit der befragten Entwickler und erreichte 2022 einen Wert von 93,9 %.

Von den befragten Entwicklern verwendete Versionskontrollsysteme:

Name 2015 2017 2018 2022
Git 69.3% 69.2% 87.2% 93.9%
Subversion 36.9% 9.1% 16.1% 5.2%
TFVC 12.2% 7.3% 10.9%
Mercurial 7.9% 1.9% 3.6% 1.13%
CVS 4.2%
Perforce 3.3%
VSS 0.6%
ClearCase 0.4%
Zip-Datei-Backups 2.0% 7.9%
Rohe Netzwerkfreigabe 1.7% 7.9%
Andere 5.8% 3.0%
Keine 9.3% 4.8% 4.8% 4.3%

Die britische IT-Job-Website itjobswatch.co.uk berichtet, dass Ende September 2016 in 29,27 % der Stellenausschreibungen für Softwareentwicklung in Großbritannien Git genannt wurde, vor 12,17 % für Microsoft Team Foundation Server, 10,60 % für Subversion, 1,30 % für Mercurial und 0,48 % für Visual SourceSafe.

Erweiterungen

Es gibt viele Git-Erweiterungen, wie z. B. Git LFS, das als Erweiterung von Git in der GitHub-Community entstand und inzwischen auch von anderen Repositories verwendet wird. Erweiterungen werden in der Regel unabhängig voneinander von verschiedenen Personen entwickelt und gepflegt, aber irgendwann in der Zukunft kann eine weit verbreitete Erweiterung in Git eingebunden werden.

Andere Open-Source-Git-Erweiterungen sind unter anderem:

  • git-annex, ein verteiltes Dateisynchronisationssystem auf der Grundlage von Git
  • git-flow, eine Reihe von Git-Erweiterungen zur Bereitstellung von Repository-Operationen auf hoher Ebene für Vincent Driessens Verzweigungsmodell
  • git-machete, ein Repository-Organizer und Werkzeug zur Automatisierung von Rebase/Merge/Pull/Push-Vorgängen

Microsoft hat die Erweiterung Virtual File System for Git (VFS for Git; früher Git Virtual File System oder GVFS) entwickelt, um die Größe des Windows-Quellcodebaums im Rahmen der Migration von Perforce im Jahr 2017 zu bewältigen. Mit VFS for Git können geklonte Repositories Platzhalter verwenden, deren Inhalt nur heruntergeladen wird, wenn auf eine Datei zugegriffen wird.

Konventionen

Git macht nicht viele Einschränkungen bei der Verwendung, aber es gibt einige Konventionen, um Geschichten zu organisieren, insbesondere solche, die die Zusammenarbeit vieler Mitwirkender erfordern.

  • Der Master-Zweig wird standardmäßig mit git init erstellt und wird oft als der Zweig verwendet, in den andere Änderungen zusammengeführt werden. Dementsprechend lautet der Standardname des vorgelagerten Remote-Zweigs origin und der Name des Standard-Remote-Zweigs ist origin/master. Die Verwendung von master als Standard-Zweigname ist nicht universell gültig. In GitHub und GitLab erstellte Repositories werden mit einem Hauptzweig anstelle von master initialisiert.
  • Gepushte Commits sollten in der Regel nicht überschrieben werden, sondern eher rückgängig gemacht werden (ein Commit wird darüber gemacht, der die Änderungen an einem früheren Commit rückgängig macht). Dadurch wird verhindert, dass neue gemeinsame Commits, die auf gemeinsamen Commits basieren, ungültig sind, weil der Commit, auf dem sie basieren, im Remote nicht existiert. Wenn die Commits sensible Informationen enthalten, sollten sie entfernt werden, was ein komplexeres Verfahren zum Umschreiben der Historie erfordert.
  • Der Arbeitsablauf und die Namenskonventionen von git-flow werden häufig verwendet, um zwischen funktionsspezifischen instabilen Historien (feature/*), instabilen gemeinsamen Historien (develop), produktionsreifen Historien (main) und Notfall-Patches für veröffentlichte Produkte (hotfix) zu unterscheiden.
  • Pull-Requests sind keine Funktion von Git, werden aber in der Regel von Git-Cloud-Diensten bereitgestellt. Eine Pull-Anfrage ist eine Anfrage eines Benutzers, einen Zweig seines Repository-Forks in ein anderes Repository mit demselben Verlauf (das sogenannte Upstream-Remote) einzubinden. Die zugrundeliegende Funktion einer Pull-Anfrage unterscheidet sich nicht von der eines Administrators eines Repositorys, der Änderungen aus einem anderen entfernten Repository (dem Repository, das die Quelle der Pull-Anfrage ist) zieht. Die Pull-Anfrage selbst ist jedoch ein Ticket, das vom Hosting-Server verwaltet wird, der Skripte zur Durchführung dieser Aktionen initiiert; sie ist keine Funktion von git SCM.

Sicherheit

Git bietet keine Mechanismen zur Zugriffskontrolle, sondern wurde für den Betrieb mit anderen Tools entwickelt, die auf die Zugriffskontrolle spezialisiert sind.

Am 17. Dezember 2014 wurde ein Exploit gefunden, der die Windows- und macOS-Versionen des Git-Clients betrifft. Ein Angreifer konnte auf einem Zielcomputer mit installiertem Git beliebigen Code ausführen, indem er einen bösartigen Git-Baum (Verzeichnis) mit dem Namen .git (ein Verzeichnis in Git-Repositorys, das alle Daten des Repositorys speichert) in einem anderen Fall (wie .GIT oder . Git, da Git die manuelle Erstellung der Kleinbuchstabenversion von .git nicht zulässt) mit bösartigen Dateien im Unterverzeichnis .git/hooks (ein Ordner mit ausführbaren Dateien, die Git ausführt) in einem Repository, das der Angreifer erstellt hat, oder in einem Repository, das der Angreifer ändern kann. Wenn ein Windows- oder Mac-Benutzer eine Version des Repositorys mit dem bösartigen Verzeichnis herunterlädt und dann in dieses Verzeichnis wechselt, wird das .git-Verzeichnis überschrieben (aufgrund der Groß- und Kleinschreibung in den Dateisystemen von Windows und Mac) und die bösartigen ausführbaren Dateien in .git/hooks können ausgeführt werden, was zur Ausführung der Befehle des Angreifers führt. Ein Angreifer könnte auch die Konfigurationsdatei .git/config ändern, was es ihm ermöglicht, bösartige Git-Aliase (Aliase für Git-Befehle oder externe Befehle) zu erstellen oder bestehende Aliase zu ändern, um bösartige Befehle auszuführen, wenn sie ausgeführt werden. Die Sicherheitslücke wurde in Version 2.2.1 von Git, die am 17. Dezember 2014 veröffentlicht wurde, gepatcht und am nächsten Tag bekannt gegeben.

Git Version 2.6.1, die am 29. September 2015 veröffentlicht wurde, enthielt einen Patch für eine Sicherheitslücke (CVE-2015-7545), die die Ausführung von beliebigem Code ermöglichte. Die Schwachstelle war ausnutzbar, wenn ein Angreifer ein Opfer dazu bringen konnte, eine bestimmte URL zu klonen, da die beliebigen Befehle in die URL selbst eingebettet waren. Ein Angreifer konnte die Schwachstelle über einen Man-in-the-Middle-Angriff ausnutzen, wenn die Verbindung unverschlüsselt war, da er den Nutzer auf eine URL seiner Wahl umleiten konnte. Rekursive Klone waren ebenfalls verwundbar, da sie dem Verwalter eines Repositorys erlaubten, beliebige URLs über die gitmodules-Datei anzugeben.

Git verwendet intern SHA-1-Hashes. Linus Torvalds hat darauf geantwortet, dass der Hash hauptsächlich zum Schutz vor versehentlicher Verfälschung diente und die Sicherheit, die ein kryptografisch sicherer Hash bietet, nur ein versehentlicher Nebeneffekt war, wobei die Hauptsicherheit anderweitig signiert wurde. Seit einer Demonstration des SHAttered-Angriffs gegen Git im Jahr 2017 wurde Git so verändert, dass es eine SHA-1-Variante verwendet, die gegen diesen Angriff resistent ist. Ein Plan für die Umstellung der Hash-Funktion wird seit Februar 2020 geschrieben.

Markenzeichen

"Git" ist eine eingetragene Wortmarke von Software Freedom Conservancy unter US500000085961336 seit 2015-02-03.

Eigenschaften

Datenfluss

Git ist ein verteiltes Versionsverwaltungssystem, das sich in einigen Eigenschaften von typischen Versionsverwaltungssystemen unterscheidet:

Säubern des Repositorys

Die Daten gelöschter und zurückgenommener Aktionen und Entwicklungszweige bleiben vorhanden (und können wiederhergestellt werden), bis sie explizit gelöscht werden.

Web-Interface

Gitweb mit den Unterschieden zwischen zwei Commits

Mit Gitweb gibt es eine in Perl geschriebene Weboberfläche. Der Team Foundation Server von Microsoft hat eine Git-Anbindung (Git-tf).

Verbreitung

Laut Open Hub verwendeten im April 2019 rund 69 % aller dort registrierten Softwareprojekte Git. Damit dominiert Git mit großem Abstand zu dem nächstplatzierten Subversion, das 25 % erreicht.

Verwendung

Verwaltung von Inhalt

Obwohl Git primär zur Versionsverwaltung von Quellcode entwickelt wurde, wird es auch zum Speichern von flach strukturierten (im Gegensatz zu relationalen Strukturen) Datensätzen direkt als Datei genutzt. So können Funktionen wie Versionsverwaltung, Hook, diff, Replikation und Offline-Nutzung auch für Inhalte ohne Datenbank genutzt werden. Die Nutzung ist ähnlich zu NoSQL, auch wenn Git keine Indexstruktur, Abfrage oder Gleichzeitigkeit erlaubt.

Der Einsatz erstreckt sich auch auf inhaltlich einfach strukturierte Systeme wie CMS oder Wikis.

Unterstützte Betriebssysteme

Unix/Linux

Git läuft auf fast allen modernen unixartigen Systemen wie Linux, Solaris, macOS, FreeBSD, DragonFly BSD, NetBSD, OpenBSD, AIX, IRIX.

Apple liefert macOS mit einer leicht abgewandelten Git-Version aus. Hauptsächlich wird diese verwendet, um die Kompatibilität mit Apples Entwicklungsumgebung Xcode zu erhöhen.