Einrichtung und Konfiguration
Projekte holen und erstellen
Grundlegende Snapshots
Branching und Merging
Projekte teilen und aktualisieren
Inspektion und Vergleich
Patching
Debugging
Externe Systeme
Server-Administration
Anleitungen
- gitattributes
- Konventionen der Kommandozeile
- Tägliches Git
- Häufig gestellte Fragen (FAQ)
- Glossar
- Hooks
- gitignore
- gitmodules
- Revisionen
- Submodule
- Tutorial
- Workflows
- Alle Anleitungen...
Administration
Plumbing-Befehle
- 2.49.1 → 2.52.0 keine Änderungen
-
2.49.0
2025-03-14
- 2.48.1 → 2.48.2 keine Änderungen
-
2.48.0
2025-01-10
- 2.43.1 → 2.47.3 keine Änderungen
-
2.43.0
2023-11-20
- 2.38.1 → 2.42.4 keine Änderungen
-
2.38.0
2022-10-02
- 2.36.1 → 2.37.7 keine Änderungen
-
2.36.0
2022-04-18
- 2.33.1 → 2.35.8 keine Änderungen
-
2.33.0
2021-08-16
- 2.29.1 → 2.32.7 keine Änderungen
-
2.29.0
2020-10-19
- 2.25.1 → 2.28.1 keine Änderungen
-
2.25.0
2020-01-13
- 2.24.1 → 2.24.4 keine Änderungen
-
2.24.0
2019-11-04
- 2.21.1 → 2.23.4 keine Änderungen
-
2.21.0
2019-02-24
- 2.19.1 → 2.20.5 keine Änderungen
-
2.19.0
2018-09-10
- 2.17.0 → 2.18.5 keine Änderungen
-
2.16.6
2019-12-06
Die Funktion "Partial Clone" ist eine Performance-Optimierung für Git, die es Git ermöglicht, ohne eine vollständige Kopie des Repositories zu funktionieren. Ziel dieser Arbeit ist es, Git die bessere Handhabung extrem großer Repositories zu ermöglichen.
Bei Klon- und Abrufoperationen lädt Git den vollständigen Inhalt und die Historie des Repositories herunter. Dies beinhaltet alle Commits, Trees und Blobs für die gesamte Lebensdauer des Repositories. Für extrem große Repositories können Klone Stunden (oder Tage) dauern und 100+ GiB Speicherplatz verbrauchen.
Oft gibt es in diesen Repositories viele Blobs und Trees, die der Benutzer nicht benötigt, wie z. B.
-
Dateien außerhalb des Arbeitsbereichs des Benutzers im Tree. In einem Repository mit 500.000 Verzeichnissen und 3,5 Millionen Dateien in jedem Commit können wir beispielsweise viele Objekte vermeiden, wenn der Benutzer nur einen schmalen "Kegel" des Quell-Trees benötigt.
-
große binäre Assets. In einem Repository, in dem große Build-Artefakte in den Tree eingecheckt sind, können wir beispielsweise vermeiden, alle früheren Versionen dieser nicht zusammenführbaren binären Assets herunterzuladen und nur Versionen herunterzuladen, auf die tatsächlich verwiesen wird.
Partial Clone ermöglicht es uns, solche unnötigen Objekte im Voraus während des Klonens und Abrufens zu vermeiden und dadurch Downloadzeiten und Speicherplatz zu reduzieren. Fehlende Objekte können später bei Bedarf "on demand" abgerufen werden.
Ein Remote, das später fehlende Objekte bereitstellen kann, wird als Promisor-Remote bezeichnet, da es verspricht, die Objekte bei Anfrage zu senden. Anfangs unterstützte Git nur eine einzige Promisor-Remote, die Origin-Remote, von der der Benutzer geklont hat und die in der Konfigurationsoption "extensions.partialClone" konfiguriert war. Später wurde die Unterstützung für mehr als eine Promisor-Remote implementiert.
Die Verwendung von Partial Clone erfordert, dass der Benutzer online ist und die Origin-Remote oder andere Promisor-Remotes für den bedarfsgesteuerten Abruf fehlender Objekte verfügbar sind. Dies kann für den Benutzer problematisch sein oder auch nicht. Wenn der Benutzer beispielsweise innerhalb des vorausgewählten Teils des Quell-Trees bleiben kann, trifft er möglicherweise auf keine fehlenden Objekte. Alternativ könnte der Benutzer versuchen, verschiedene Objekte im Voraus abzurufen, wenn er weiß, dass er offline gehen wird.
Nicht-Ziele
Partial Clone ist ein Mechanismus, um die Anzahl der heruntergeladenen Blobs und Trees innerhalb eines gegebenen Commit-Bereichs zu begrenzen – und ist daher unabhängig von und nicht dazu gedacht, mit bestehenden DAG-Level-Mechanismen zur Begrenzung der Menge der angeforderten Commits zu kollidieren (d.h. Shallow Clone, Single Branch oder Fetch <refspec>).
Design-Übersicht
Partial Clone besteht logischerweise aus folgenden Teilen
-
Ein Mechanismus, damit der Client dem Server unerwünschte oder nicht benötigte Objekte beschreiben kann.
-
Ein Mechanismus, damit der Server solche unerwünschten Objekte aus den Packfiles weglassen kann, die an den Client gesendet werden.
-
Ein Mechanismus, damit der Client fehlende Objekte (die zuvor vom Server weggelassen wurden) ordnungsgemäß behandeln kann.
-
Ein Mechanismus, damit der Client fehlende Objekte bei Bedarf auffüllen kann.
Design-Details
-
Eine neue Pack-Protokoll-Fähigkeit "filter" wird zur Fetch-Pack- und Upload-Pack-Aushandlung hinzugefügt.
Dies nutzt den bestehenden Mechanismus zur Fähigkeitserkennung. Siehe "filter" in gitprotocol-pack[5].
-
Clients übergeben einen "filter-spec" an Clone und Fetch, der an den Server übergeben wird, um die Filterung während der Packfile-Erstellung anzufordern.
Es gibt verschiedene Filter, die für unterschiedliche Situationen verfügbar sind. Siehe "--filter=<filter-spec>" in Documentation/rev-list-options.adoc.
-
Auf der Serverseite wendet `pack-objects` den angeforderten filter-spec an, während es "gefilterte" Packfiles für den Client erstellt.
Diese gefilterten Packfiles sind im herkömmlichen Sinne unvollständig, da sie Objekte enthalten können, die auf Objekte verweisen, die nicht in der Packfile enthalten sind und die der Client noch nicht hat. Zum Beispiel kann die gefilterte Packfile Trees oder Tags enthalten, die auf fehlende Blobs verweisen, oder Commits, die auf fehlende Trees verweisen.
-
Auf der Clientseite werden diese unvollständigen Packfiles als "Promisor Packfiles" gekennzeichnet und von verschiedenen Befehlen unterschiedlich behandelt.
-
Auf der Clientseite wird eine Repository-Erweiterung zur lokalen Konfiguration hinzugefügt, um zu verhindern, dass ältere Git-Versionen mitten im Vorgang aufgrund fehlender Objekte, die sie nicht handhaben können, fehlschlagen. Siehe
extensions.partialClonein git-config[1].
Umgang mit fehlenden Objekten
-
Ein Objekt kann aufgrund eines partiellen Klons oder Abrufs fehlen oder aufgrund von Repository-Beschädigungen. Um diese Fälle zu unterscheiden, kennzeichnet das lokale Repository solche gefilterten Packfiles, die von Promisor-Remotes bezogen wurden, speziell als "Promisor Packfiles".
Diese Promisor Packfiles bestehen aus einer "<Name>.promisor"-Datei mit beliebigem Inhalt (ähnlich wie die "<Name>.keep"-Dateien) zusätzlich zu ihren "<Name>.pack"- und "<Name>.idx"-Dateien.
-
Das lokale Repository betrachtet ein "Promisor-Objekt" als ein Objekt, von dem es (nach bestem Wissen und Gewissen) weiß, dass Promisor-Remotes versprochen haben, es zu haben, entweder weil das lokale Repository dieses Objekt in einer seiner Promisor Packfiles hat, oder weil ein anderes Promisor-Objekt darauf verweist.
Wenn Git auf ein fehlendes Objekt stößt, kann Git prüfen, ob es sich um ein Promisor-Objekt handelt und es entsprechend behandeln. Wenn nicht, kann Git eine Beschädigung melden.
Das bedeutet, dass der Client keine explizit kostspielige Liste fehlender Objekte pflegen muss.[a]
-
Da fast alle Git-Codes derzeit erwarten, dass jedes referenzierte Objekt lokal vorhanden ist, und wir nicht jeden Befehl dazu zwingen wollen, zuerst eine Trockenlaufprüfung durchzuführen, wird ein Fallback-Mechanismus hinzugefügt, der es Git ermöglicht, fehlende Objekte dynamisch von Promisor-Remotes abzurufen.
Wenn die normale Objektsuche fehlschlägt, ein Objekt zu finden, ruft Git `promisor_remote_get_direct()` auf, um zu versuchen, das Objekt von einer Promisor-Remote zu erhalten, und versucht dann die Objektsuche erneut. Dies ermöglicht es, Objekte "on demand" zu laden, ohne komplizierte Vorhersagealgorithmen.
Aus Effizienzgründen wird keine Prüfung durchgeführt, ob das fehlende Objekt tatsächlich ein Promisor-Objekt ist.
Dynamisches Objekt-Abrufen ist tendenziell langsam, da Objekte einzeln abgerufen werden.
-
checkout(und jeder andere Befehl, derunpack-treesverwendet) wurde so erweitert, dass alle benötigten fehlenden Blobs in einem einzigen Stapel vorgeladen werden. -
rev-listwurde so erweitert, dass es fehlende Objekte ausgibt.Dies kann von anderen Befehlen verwendet werden, um Objekte stapelweise vorab abzurufen. Beispielsweise könnte ein "git log -p A..B" intern etwas wie "git rev-list --objects --quiet --missing=print A..B" ausführen und diese Objekte stapelweise vorab abrufen.
-
fsckwurde aktualisiert, um vollständig über Promisor-Objekte informiert zu sein. -
repackin GC wurde aktualisiert, um Promisor-Packfiles überhaupt nicht zu berühren und nur andere Objekte neu zu verpacken. -
Die globale Variable "fetch_if_missing" wird verwendet, um zu steuern, ob eine Objektsuche versucht, ein fehlendes Objekt dynamisch abzurufen, oder einen Fehler meldet.
Wir sind mit dieser globalen Variable nicht zufrieden und möchten sie entfernen, dies erfordert jedoch eine signifikante Refaktorierung des Objektcodes, um ein zusätzliches Flag zu übergeben.
Fehlende Objekte abrufen
-
Das Abrufen von Objekten erfolgt durch Aufruf eines "git fetch"-Subprozesses.
-
Das lokale Repository sendet eine Anfrage mit den Hashes aller angeforderten Objekte und führt keine Packfile-Aushandlung durch. Es empfängt dann eine Packfile.
-
Da wir den bestehenden Abrufmechanismus wiederverwenden, ruft der Abruf derzeit alle von den angeforderten Objekten referenzierten Objekte ab, auch wenn diese nicht notwendig sind.
-
Das Abrufen mit
--refetchfordert eine vollständige neue gefilterte Packfile vom Remote an, die verwendet werden kann, um einen Filter zu ändern, ohne fehlende Objekte dynamisch abrufen zu müssen.
Verwendung vieler Promisor-Remotes
Viele Promisor-Remotes können konfiguriert und verwendet werden.
Dies ermöglicht es beispielsweise einem Benutzer, mehrere geografisch nahegelegene Cache-Server zum Abrufen fehlender Blobs zu haben, während weiterhin gefilterte git-fetch-Befehle vom zentralen Server ausgeführt werden.
Beim Abrufen von Objekten werden Promisor-Remotes nacheinander versucht, bis alle Objekte abgerufen wurden.
Remotes, die als "Promisor"-Remotes gelten, sind diejenigen, die durch die folgenden Konfigurationsvariablen angegeben werden
-
extensions.partialClone=<name> -
remote.<name>.promisor=true -
remote.<name>.partialCloneFilter=...
Nur ein Promisor-Remote kann über die Konfigurationsvariable extensions.partialClone konfiguriert werden. Dieser Promisor-Remote ist der letzte, der beim Abrufen von Objekten versucht wird.
Wir haben beschlossen, ihn als letzten zu versuchen, da es wahrscheinlich ist, dass jemand, der viele Promisor-Remotes verwendet, dies tut, weil die anderen Promisor-Remotes aus irgendeinem Grund besser sind (vielleicht sind sie näher oder schneller für bestimmte Arten von Objekten) als die Origin, und die Origin ist wahrscheinlich das Remote, das von `extensions.partialClone` angegeben wird.
Diese Begründung ist nicht sehr stark, aber eine Entscheidung musste getroffen werden, und ohnehin sollte der langfristige Plan darin bestehen, die Reihenfolge irgendwie vollständig konfigurierbar zu machen.
Fürs Erste werden die anderen Promisor-Remotes jedoch in der Reihenfolge versucht, in der sie in der Konfigurationsdatei erscheinen.
Aktuelle Einschränkungen
-
Es ist nicht möglich, die Reihenfolge, in der die Promisor-Remotes versucht werden, anders als durch die Reihenfolge, in der sie in der Konfigurationsdatei erscheinen, anzugeben.
Es ist auch nicht möglich, eine Reihenfolge anzugeben, die beim Abrufen von einem Remote verwendet wird, und eine andere Reihenfolge beim Abrufen von einem anderen Remote.
-
Es ist nicht möglich, nur bestimmte Objekte an ein Promisor-Remote zu pushen.
Es ist nicht möglich, gleichzeitig an mehrere Promisor-Remotes in einer bestimmten Reihenfolge zu pushen.
-
Dynamisches Objekt-Abrufen fragt nur Promisor-Remotes nach fehlenden Objekten ab. Wir gehen davon aus, dass Promisor-Remotes eine vollständige Ansicht des Repositories haben und alle solchen Anfragen erfüllen können.
-
Repack behandelt Promisor- und Nicht-Promisor-Packfiles im Wesentlichen als 2 getrennte Partitionen und mischt sie nicht.
-
Dynamisches Objekt-Abrufen ruft `fetch-pack` für jedes Element einmal auf, da die meisten Algorithmen auf ein fehlendes Objekt stoßen und es vor der Fortsetzung ihrer Arbeit auflösen müssen. Dies kann zu erheblichen Mehraufwand führen – und zu mehreren Authentifizierungsanfragen –, wenn viele Objekte benötigt werden.
-
Dynamisches Objekt-Abrufen verwendet derzeit das bestehende Pack-Protokoll V0, was bedeutet, dass jedes Objekt über `fetch-pack` angefordert wird. Der Server sendet bei Herstellen der Verbindung einen vollständigen Satz von `info/refs`. Wenn es eine große Anzahl von Refs gibt, kann dies zu erheblichem Mehraufwand führen.
Zukünftige Arbeiten
-
Verbessern Sie die Methode zur Angabe der Reihenfolge, in der Promisor-Remotes versucht werden.
Dies könnte beispielsweise die explizite Angabe ermöglichen, wie z. B.: "Beim Abrufen von diesem Remote möchte ich diese Promisor-Remotes in dieser Reihenfolge verwenden, aber beim Pushen oder Abrufen zu jenem Remote möchte ich jene Promisor-Remotes in jener Reihenfolge verwenden."
-
Erlauben Sie das Pushen an Promisor-Remotes.
Der Benutzer möchte möglicherweise in einem dreieckigen Workflow mit mehreren Promisor-Remotes arbeiten, die jeweils eine unvollständige Ansicht des Repositories haben.
-
Erlauben Sie nicht-Pfad-basierten Filtern, Packfile-Bitmaps (falls vorhanden) zu nutzen. Dies war nur eine Auslassung während der anfänglichen Implementierung.
-
Untersuchen Sie die Verwendung eines langlaufenden Prozesses, um eine Reihe von Objekten dynamisch abzurufen, wie in [5,6] vorgeschlagen, um Prozessstart- und Overhead-Kosten zu reduzieren.
Es wäre schön, wenn das Pack-Protokoll V2 es diesem langlaufenden Prozess ermöglichen würde, eine Reihe von Anfragen über eine einzige langlaufende Verbindung zu stellen.
-
Untersuchen Sie das Pack-Protokoll V2, um die `info/refs`-Übertragung bei jeder Verbindung mit dem Server zu vermeiden, um fehlende Objekte dynamisch abzurufen.
-
Untersuchen Sie die Notwendigkeit der Handhabung loser Promisor-Objekte.
Objekte in Promisor Packfiles dürfen auf fehlende Objekte verweisen, die dynamisch vom Server abgerufen werden können. Es wurde die Annahme getroffen, dass lose Objekte nur lokal erstellt werden und daher nicht auf ein fehlendes Objekt verweisen sollten. Möglicherweise müssen wir diese Annahme überdenken, wenn wir beispielsweise einen fehlenden Tree dynamisch abrufen und ihn als loses Objekt und nicht als Einzelobjekt-Packfile speichern.
Dies bedeutet nicht unbedingt, dass wir lose Objekte als Promisor markieren müssen; es könnte ausreichen, die Funktionen für die Objektsuche oder "is-promisor" zu lockern.
Nicht-Aufgaben
-
Jedes Mal, wenn das Thema "demand loading blobs" aufkommt, scheint jemand vorzuschlagen, dass dem Server erlaubt werden soll zu "raten" und zusätzliche Objekte zu senden, die möglicherweise mit den angeforderten Objekten zusammenhängen.
Es wurde keine Arbeit geleistet, um dies tatsächlich umzusetzen; wir dokumentieren nur, dass es ein häufiger Vorschlag ist. Wir sind uns nicht sicher, wie es funktionieren würde, und haben keine Pläne, daran zu arbeiten.
Es ist gültig, dass der Server mehr Objekte als angefordert sendet (auch bei einem dynamischen Objekt-Abruf), aber wir bauen darauf nicht auf.
Fußnoten
[a] kostspielige Liste fehlender Objekte: Früher im Design von Partial Clone diskutierten wir die Notwendigkeit einer einzigen Liste fehlender Objekte. Dies wäre im Wesentlichen eine sortierte lineare Liste von OIDs, die vom Server während eines Klons oder nachfolgender Abrufe weggelassen wurden.
Diese Datei müsste bei jeder Objektsuche in den Speicher geladen werden. Sie müsste bei jedem expliziten "git fetch"-Befehl und bei jedem dynamischen Objekt-Abruf gelesen, aktualisiert und neu geschrieben werden (ähnlich wie die .git/index).
Die Kosten für das Lesen, Aktualisieren und Schreiben dieser Datei könnten zu jedem Befehl erhebliche Mehraufwände hinzufügen, wenn viele Objekte fehlen. Wenn es beispielsweise 100 Millionen fehlende Blobs gibt, wäre diese Datei mindestens 2 GiB groß auf der Festplatte.
Mit dem "Promisor"-Konzept leiten wir ein fehlendes Objekt ab, basierend auf der Art der Packfile, die darauf verweist.
Verwandte Links
[0] https://crbug.com/git/2 Bug#2: Partial Clone
[1] https://lore.kernel.org/git/20170113155253.1644-1-benpeart@microsoft.com/
Betreff: [RFC] Unterstützung für das Herunterladen von Blobs bei Bedarf hinzufügen
Datum: Fr, 13. Jan. 2017 10:52:53 -0500
[2] https://lore.kernel.org/git/cover.1506714999.git.jonathantanmy@google.com/
Betreff: [PATCH 00/18] Partial Clone (von Clone bis Lazy Fetch in 18 Patches)
Datum: Fr, 29. Sep. 2017 13:11:36 -0700
[3] https://lore.kernel.org/git/20170426221346.25337-1-jonathantanmy@google.com/
Betreff: Vorschlag für fehlende Blob-Unterstützung in Git-Repos
Datum: Mi, 26. Apr. 2017 15:13:46 -0700
[4] https://lore.kernel.org/git/1488999039-37631-1-git-send-email-git@jeffhostetler.com/
Betreff: [PATCH 00/10] RFC Partial Clone and Fetch
Datum: Mi, 8. Mär. 2017 18:50:29 +0000
[5] https://lore.kernel.org/git/20170505152802.6724-1-benpeart@microsoft.com/
Betreff: [PATCH v7 00/10] Refactor den Filterprozesscode in ein wiederverwendbares Modul
Datum: Fr, 5. Mai 2017 11:27:52 -0400
[6] https://lore.kernel.org/git/20170714132651.170708-1-benpeart@microsoft.com/
Betreff: [RFC/PATCH v2 0/1] Unterstützung für das Herunterladen von Blobs bei Bedarf hinzufügen
Datum: Fr, 14. Jul. 2017 09:26:50 -0400