Partial Clone und Shallow Clone: Schnelleres Klonen großer Historien
AI generated
git
HEAD
Git
Partial Clone und Shallow Clone
Schnelleres Klonen großer Historien

Ein vollständiger git clone überträgt jede Version jeder Datei aus der gesamten Historie, auch wenn nur der aktuelle Stand benötigt wird. Partial Clone und Shallow Clone reduzieren die übertragene Datenmenge auf unterschiedliche Weise und eignen sich für unterschiedliche Einsatzszenarien, von CI Runnern bis zu Entwicklerarbeitsplätzen.

10 Min. Lesezeit Git Performance CI/CD

1. Warum große Historien beim Klonen zum Problem werden

Ein Repository mit zehn Jahren Historie, tausenden Commits und großen Binärdateien kann problemlos mehrere Gigabyte an Objektdaten ansammeln, selbst wenn der aktuelle Stand des Codes vergleichsweise klein ist. Ein Standard git clone lädt jedoch grundsätzlich alle Commits, alle Baum Objekte und alle Blob Objekte jeder jemals committeten Datei herunter, unabhängig davon, ob sie für die aktuelle Arbeit relevant sind.

Für CI Pipelines, die pro Lauf ein frisches Repository klonen, summiert sich diese unnötige Datenmenge schnell zu spürbaren Zeit und Kostenfaktoren. Auch Entwickler, die nur am aktuellen Stand arbeiten wollen und selten in die Historie zurückgehen, profitieren davon, wenn Git nicht jede jemals existierende Version jeder Datei vorab herunterladen muss.

2. Shallow Clone: Historie auf wenige Commits begrenzen

Shallow Clone begrenzt die Anzahl der übertragenen Commits über das Flag --depth. Statt der kompletten Historie erhält der Client nur die letzten n Commits jedes geklonten Branches, dargestellt durch spezielle Grenz Commits, die Git als shallow markiert und deren Elternbeziehung im lokalen Repository nicht weiter aufgelöst wird.

Der große Vorteil ist die Einfachheit: Ein --depth=1 Clone lädt praktisch nur den aktuellen Snapshot, was für CI Builds, die lediglich den aktuellen Stand kompilieren oder testen müssen, ideal ist. Der Nachteil zeigt sich, sobald Historie gebraucht wird, etwa bei git blame, git log über ältere Commits oder einem git bisect, die in einer flachen Historie nur eingeschränkt funktionieren.


# Nur den letzten Commit jedes Branches herunterladen
git clone --depth=1 https://git.example.com/repo.git

# Nachträglich zusätzliche Historie nachladen
git fetch --deepen=50

# Vollständige Historie nachträglich wiederherstellen
git fetch --unshallow

3. Partial Clone: Objekte statt Commits filtern

Partial Clone verfolgt einen anderen Ansatz als Shallow Clone: Statt die Anzahl der Commits zu begrenzen, bleibt die vollständige Commit Historie und Baumstruktur erhalten, aber bestimmte Objekttypen, meist große Blob Objekte, werden erst bei Bedarf nachgeladen. Damit funktionieren Befehle wie git log sofort vollständig, während der tatsächliche Dateiinhalt für ältere Commits erst beim Zugriff vom Server angefordert wird.

Möglich wird das durch das --filter Flag, das seit Git 2.19 existiert und dem Server mitteilt, welche Objekttypen beim initialen Clone weggelassen werden dürfen. Der Server muss dafür Partial Clone unterstützen, was bei modernen Hosting Anbietern wie GitHub, GitLab und selbst gehosteten Git Servern mit aktueller Version standardmäßig der Fall ist.


# Alle Blob Objekte erst bei Bedarf nachladen, Historie bleibt vollständig
git clone --filter=blob:none https://git.example.com/repo.git

# Zusätzlich auch Baum Objekte jenseits der Wurzel erst bei Bedarf laden
git clone --filter=tree:0 https://git.example.com/repo.git

4. Filter Varianten im Detail: blob:none, blob:limit und tree:0

Der Filter blob:none ist der gebräuchlichste: Er lädt keinerlei Dateiinhalte vor, sondern nur Commits und Baumstruktur, und lädt jeden Blob genau dann nach, wenn ein Checkout oder git show ihn tatsächlich benötigt. Der Filter blob:limit=1m ist ein Kompromiss, der kleine Dateien sofort überträgt, aber große Blobs oberhalb der angegebenen Größe auslagert, was sich für Repositories mit wenigen sehr großen Assets eignet.

Der Filter tree:0 geht noch einen Schritt weiter und lädt auch Baum Objekte für Verzeichnisse jenseits der Wurzel erst on demand. Kombiniert mit Sparse Checkout ergibt sich daraus die minimalste Datenübertragung überhaupt, weil weder Baum noch Blob Objekte für Verzeichnisse geladen werden, die im Sparse Profil ohnehin nicht sichtbar sind.


# Kleine Dateien sofort laden, große Blobs erst bei Bedarf
git clone --filter=blob:limit=1m https://git.example.com/repo.git

# Partial Clone und Sparse Checkout für minimale Datenübertragung kombinieren
git clone --filter=blob:none --sparse https://git.example.com/monorepo.git

5. Wie fehlende Objekte im Hintergrund nachgeladen werden

Sobald ein Befehl wie git checkout, git log -p oder git blame auf ein noch nicht lokal vorhandenes Objekt trifft, fragt Git es automatisch beim sogenannten Promisor Remote nach, also dem Server, der beim Clone als Quelle für nachträglich benötigte Objekte hinterlegt wurde. Dieser Vorgang läuft transparent ab, ist aber netzwerkabhängig und kann bei langsamer Verbindung einzelne Befehle spürbar verlangsamen.

Für Operationen, die viele historische Objekte auf einmal anfordern, etwa ein vollständiges git log -p über die gesamte Historie, kann das Nachladen viele einzelne Serveranfragen auslösen. In solchen Fällen empfiehlt sich ein gezieltes git fetch --filter=blob:none --unshallow oder das bewusste Nachladen mit git backfill, sofern die Git Version dieses seit 2.30 verfügbare Kommando bereits unterstützt.


# Prüfen, welche Objekte lokal fehlen und als Promisor markiert sind
git rev-list --objects --all --missing=print | head

# Fehlende Blob Objekte für den aktuellen Branch gezielt nachladen
git backfill

6. Partial Clone und Shallow Clone in CI Pipelines

In CI Pipelines ist die richtige Wahl stark vom Job Typ abhängig: Ein Job, der nur den aktuellen Stand baut und testet, profitiert am meisten von --depth=1, weil dort schlicht keine Historie benötigt wird. Ein Job, der Changed Files gegenüber einem Ziel Branch ermitteln muss, braucht dagegen zumindest die gemeinsame Historie beider Branches und scheitert mit einem zu flachen Clone an fehlenden Merge Base Commits.

Für solche Fälle liefert Partial Clone oft das bessere Verhältnis, weil die vollständige Commit Historie erhalten bleibt und nur die teuren Blob Objekte eingespart werden. Viele CI Systeme unterstützen mittlerweile GIT_CLONE_FILTER Umgebungsvariablen oder entsprechende Pipeline Optionen, um Partial Clone projektweit als Standard zu setzen.


# Beispiel für eine CI Konfiguration mit Partial Clone
variables:
  GIT_STRATEGY: clone
  GIT_CLONE_FILTER: "blob:none"
  GIT_DEPTH: "0"

7. Partial Clone in Kombination mit Submodulen

Partial Clone wirkt zunächst nur auf das Hauptrepository, während eingebundene Submodule standardmäßig vollständig geklont werden, sobald sie initialisiert werden. Wer ein Repository mit vielen großen Submodulen klont, verliert dadurch schnell wieder den Geschwindigkeitsvorteil, den Partial Clone für das Hauptrepository eigentlich bringen sollte, weil jeder Submodule Checkout erneut die vollständige Objektmenge des jeweiligen Submodule Repositories herunterlädt.

Seit Git 2.36 lässt sich der Filter mit dem Flag --also-filter-submodules automatisch auch auf rekursiv initialisierte Submodule anwenden, sodass Blob Objekte in Submodulen ebenso erst bei Bedarf nachgeladen werden wie im Hauptrepository. In älteren Git Versionen muss der Filter für jedes Submodule manuell mit git submodule update --init --filter=blob:none angewendet werden, was in Skripten für die Erstkonfiguration eines Arbeitsplatzes explizit berücksichtigt werden sollte.


# Partial Clone Filter automatisch auch auf Submodule anwenden
git clone --filter=blob:none --also-filter-submodules --recurse-submodules https://git.example.com/repo.git

# Ältere Git Version: Filter manuell pro Submodule anwenden
git submodule update --init --filter=blob:none

8. Best Practices für die Wahl der richtigen Strategie

Als Faustregel gilt: --depth=1 für isolierte Build und Test Jobs ohne Historienbedarf, --filter=blob:none für alles, was Historie braucht, aber nicht jede Datei in jeder Version. Entwicklerarbeitsplätze sollten in der Regel Partial Clone statt Shallow Clone verwenden, weil sie oft doch einmal git blame oder ältere Commits brauchen und ein nachträgliches --unshallow teurer ist als das transparente Nachladen einzelner Blobs.

Große Binärdateien gehören unabhängig von Partial Clone in ein dediziertes System wie Git LFS, weil Partial Clone die Blobs zwar verzögert lädt, sie beim tatsächlichen Zugriff aber weiterhin vollständig in die lokale Objektdatenbank überträgt und dort dauerhaft speichert.

9. Typische Fallstricke bei flachen und partiellen Klonen

Ein häufiger Fehler ist der Versuch, in einem Shallow Clone einen Branch zu pushen, der auf einem nicht vorhandenen Grenz Commit basiert, was Git mit einer Fehlermeldung über fehlende Vorfahren quittiert. Ebenso scheitern viele CI Tools, die Merge Base Berechnungen für Diff Ansichten benötigen, an zu flachen Klonen, weil der gemeinsame Vorfahre zweier Branches außerhalb der geladenen Tiefe liegt.

Bei Partial Clone ist die Falle subtiler: Wer offline arbeitet oder der Promisor Remote nicht mehr erreichbar ist, kann plötzlich auf einen Fehler stoßen, sobald ein noch nicht lokal vorhandenes Objekt benötigt wird. Vor längeren Offline Phasen empfiehlt sich deshalb ein gezieltes git backfill oder ein vollständiger --unshallow beziehungsweise Filter Reset.

Strategie Was wird begrenzt Historie verfügbar Typischer Einsatz
Shallow Clone --depth=1 Anzahl der Commits Nur letzter Commit pro Branch Isolierte CI Build und Test Jobs
Partial Clone --filter=blob:none Dateiinhalte, Blobs Vollständig, Blobs on demand Entwicklerarbeitsplätze, Diff Jobs
Partial Clone --filter=tree:0 Dateiinhalte und Verzeichnisstruktur Vollständig, Bäume on demand Kombination mit Sparse Checkout
Vollständiger Clone Nichts Vollständig, sofort lokal Langfristige Offline Arbeit, Archivierung

Mironsoft

Git-Workflows, Branching-Strategien und CI-Hooks

Chaotische Git-Historie und unklare Branching-Regeln im Team?

Wir richten saubere Git-Workflows ein, klären Branching-Strategien fürs Team und automatisieren Qualitätschecks über Git-Hooks und CI-Pipelines, damit die Historie nachvollziehbar bleibt.

Workflow-Audit

Bestehende Branching-Strategie und Merge-Praxis auf Schwachstellen prüfen.

Hook-Automatisierung

Pre-Commit- und Pre-Push-Hooks für Linting, Tests und Commit-Konventionen einrichten.

Team-Schulung

Rebase, Cherry-Pick und Konfliktauflösung im Team praxisnah vermitteln.

10. Zusammenfassung

Partial und Shallow Clone

Shallow Clone

Begrenzt Commit Anzahl, Historie unvollständig

Partial Clone

Historie vollständig, Blobs werden on demand geladen

Kernbefehl

git clone --filter=blob:none

CI Faustregel

depth=1 ohne Historienbedarf, sonst Partial Clone

11. FAQ: Partial und Shallow Clone

1Was ist der grundsätzliche Unterschied zwischen Shallow Clone und Partial Clone?
Shallow Clone begrenzt die Anzahl der Commits und lässt ältere Historie komplett weg. Partial Clone behält die vollständige Commit Historie, lädt aber Dateiinhalte erst dann herunter, wenn sie tatsächlich benötigt werden.
2Kann ich einen Shallow Clone nachträglich vervollständigen?
Ja, mit git fetch --unshallow wird die komplette Historie nachgeladen. Mit git fetch --deepen=n lässt sich alternativ nur eine begrenzte Anzahl weiterer Commits ergänzen, ohne gleich die gesamte Historie zu laden.
3Funktioniert git blame in einem Shallow Clone?
Nur eingeschränkt: git blame kann eine Aenderung nicht über den Grenz Commit hinaus zurückverfolgen und zeigt diesen dann als vermeintlichen Ursprung der Zeile an, auch wenn die tatsächliche Aenderung früher passiert ist.
4Was passiert, wenn ich in einem Partial Clone offline arbeite?
Solange alle benötigten Objekte bereits lokal nachgeladen wurden, funktioniert die Arbeit normal. Wird ein noch nicht heruntergeladenes Objekt angefordert und ist der Promisor Remote nicht erreichbar, schlägt der jeweilige Befehl mit einem Fehler fehl.
5Muss der Server Partial Clone explizit unterstützen?
Ja, der Server muss das uploadpack.allowFilter Feature aktiviert haben. Moderne Hosting Plattformen wie GitHub und GitLab sowie aktuelle Versionen von selbst gehosteten Git Servern unterstützen dies standardmäßig.
6Ersetzt Partial Clone die Notwendigkeit von Git LFS?
Nein, Partial Clone verzögert lediglich den Download bereits committeter Blobs, speichert sie beim Zugriff aber weiterhin vollständig lokal. Für sehr große Binärdateien bleibt Git LFS mit externem Speicher die geeignetere Lösung.
7Welcher Filter eignet sich für Monorepos mit Sparse Checkout?
Die Kombination aus --filter=blob:none oder --filter=tree:0 mit --sparse liefert die geringste Datenmenge, weil weder Baum noch Blob Objekte für nicht sichtbare Verzeichnisse geladen werden.
8Wie erkenne ich, ob ein lokales Repository ein Shallow Clone ist?
Die Datei .git/shallow existiert nur in flachen Repositories und listet die Grenz Commits auf. Zusätzlich meldet git rev-parse --is-shallow-repository true oder false.
9Kann ein CI Job Partial Clone und Shallow Clone gleichzeitig nutzen?
Ja, beide Flags lassen sich kombinieren, etwa --depth=1 zusammen mit --filter=blob:none, wobei der praktische Zusatznutzen meist gering ist, weil ein Depth von 1 ohnehin kaum historische Blobs anfordert.
10Welche Git Version wird für Partial Clone mindestens benötigt?
Client seitig ist Partial Clone seit Git 2.19 verfügbar, produktionsreif und mit breiter Server Unterstützung jedoch erst ab Git 2.22. Aktuelle Git Versionen ab 2.30 aufwärts werden für den produktiven Einsatz empfohlen.