Fehlerbehebung bei langsamen Git-Operationen: Häufige Fallstricke und Lösungen

Diagnostizieren Sie langsame Git-Befehle, indem Sie Ursachen wie Status, Clone, Fetch, Push, Hooks, Dateisystem, Netzwerk und Repository-Größe trennen.

Fehlerbehebung bei langsamen Git-Operationen: Häufige Fallstricke und Lösungen

Langsames Git hat unterschiedliche Ursachen, je nachdem, welcher Befehl langsam ist. Ein langsames git status liegt normalerweise am lokalen Dateisystem oder an der Indexarbeit. Ein langsames git fetch ist oft auf das Netzwerk, die Größe des entfernten Repositories oder die Verhandlung zurückzuführen. Ein langsames git checkout kann an der Dateianzahl, der Antivirenprüfung, Problemen mit dem Sparse Checkout oder generierten Dateien liegen. Ein langsames git push kann an großen Objekten, Hooks, Komprimierung oder dem entfernten Server liegen.

Die erste Lösung ist also nicht git gc. Die erste Lösung besteht darin, die genaue Operation zu messen.

Unter macOS oder Linux:

time git status
time git fetch --prune
time git checkout main

Unter PowerShell:

Measure-Command { git status }

Führen Sie den Befehl zweimal aus. Der erste Durchlauf kann langsamer sein, da der Betriebssystem-Cache kalt ist. Wenn der erste git status zehn Sekunden und der zweite eine Sekunde dauert, liegt möglicherweise ein Problem mit dem Festplatten-Cache vor. Wenn beide langsam sind, graben Sie weiter.

Git hat eine integrierte Ablaufverfolgung, die zeigen kann, wo die Zeit bleibt:

GIT_TRACE=1 git status
GIT_TRACE_PERFORMANCE=1 git status
GIT_TRACE_PACKET=1 GIT_TRACE=1 git fetch

GIT_TRACE_PACKET ist laut, aber nützlich, wenn Fetch oder Push während der Protokollverhandlung hängen bleiben. Fügen Sie keine Trace-Ausgaben mit privaten Repository-URLs oder Token in öffentliche Tickets ein.

Wenn git status langsam ist

git status überprüft den Index und das Arbeitsverzeichnis. Es wird langsam, wenn das Repository eine große Anzahl von Dateien hat, das Arbeitsverzeichnis auf einem langsamen Dateisystem liegt, Dateimetadaten teuer zu lesen sind oder ein anderes Programm jede Datei scannt, die Git berührt.

Beginnen Sie mit den Grundlagen:

git status --short
git config --show-origin --get core.fsmonitor
git config --show-origin --get core.untrackedCache
git config --show-origin --get core.preloadIndex

Für große Arbeitsverzeichnisse können diese Einstellungen auf vielen Systemen helfen:

git config core.untrackedCache true
git config core.preloadIndex true

Verwenden Sie zuerst die lokale Konfiguration, damit Sie pro Repository testen können. Wenn es hilft, machen Sie es später global.

Der integrierte Dateisystem-Monitor von Git kann den Status beschleunigen, indem er vollständige Scans auf unterstützten Plattformen und Git-Versionen vermeidet:

git config core.fsmonitor true

Wenn der Status nach der Aktivierung falsch oder seltsam wird, deaktivieren Sie ihn und aktualisieren Sie Git, bevor Sie es erneut versuchen:

git config --unset core.fsmonitor

Unverfolgte Dateien können ein verstecktes Problem sein. Build-Ausgaben, Abhängigkeitsverzeichnisse, generierte Berichte und lokale Protokolle sollten normalerweise ignoriert werden. Überprüfen Sie, was Git scannt:

git status --untracked-files=all --short | head -100

Wenn Sie node_modules/, dist/, .venv/, target/ oder ähnliche generierte Verzeichnisse sehen, fügen Sie die richtigen Muster zu .gitignore hinzu. Ignorieren Sie keine Quelldateien, nur um den Status zu beschleunigen. Ignorieren Sie Dateien, die wirklich nicht versioniert werden sollten.

Unter Windows ist die Echtzeit-Antivirenprüfung ein häufiger Grund, warum Git sich langsam anfühlt. Git liest viele kleine Dateien in .git und im Arbeitsverzeichnis, und Sicherheitssoftware kann jeden Zugriff überprüfen. Wenn Ihre Organisation es erlaubt, schließen Sie vertrauenswürdige Entwicklungsumgebungen von der Echtzeitprüfung aus. Schließen Sie keine Verzeichnisse aus, in denen Sie nicht vertrauenswürdigen Code ausführen.

Vermeiden Sie es auch, aktive Repositories in Cloud-Synchronisationsordnern wie OneDrive, Dropbox oder iCloud Drive zu platzieren. Synchronisationstools können Dateien sperren, Metadaten umschreiben und mit Gits eigenen Dateioperationen konkurrieren.

Wenn Clone oder Fetch langsam ist

Ein langsamer Clone kann eine große Historie, viele große Blobs, einen langsamen entfernten Server oder einen Netzwerkpfad mit hoher Latenz bedeuten. Messen Sie die Repository-Größe nach dem Klonen:

git count-objects -vH
du -sh .git 2>/dev/null

Für CI-Jobs und temporäre Umgebungen verwenden Sie einen flachen Clone, wenn die Historie nicht benötigt wird:

git clone --depth 1 <url>

Für einen Branch-Build:

git clone --depth 1 --branch main <url>

Flache Clones sind nicht für jeden Workflow ideal. Befehle, die Historie, Tags, Merge-Basen oder Versionsberechnungen benötigen, können fehlschlagen oder unvollständige Antworten liefern. In CI ist das oft akzeptabel. Auf einem Entwicklerrechner kann es frustrierend sein.

Partieller Clone ist nützlich, wenn die Repository-Historie benötigt wird, aber Datei-Blobs träge heruntergeladen werden können:

git clone --filter=blob:none <url>

Dies funktioniert am besten mit modernen Git-Servern, die partiellen Clone gut unterstützen. Testen Sie es mit Ihrem Host, bevor Sie es zur offiziellen Teamempfehlung machen.

Wenn Sie nur einen Teil eines Monorepos benötigen, kombinieren Sie Sparse Checkout mit einem normalen oder partiellen Clone:

git clone --filter=blob:none --sparse <url>
cd repo
git sparse-checkout set services/api shared/lib

Sparse Checkout reduziert die Größe des Arbeitsverzeichnisses. Es macht nicht magisch jede Git-Operation billig, aber es hilft, wenn die Dateianzahl das Hauptproblem ist.

Bei Fetches mit vielen gelöschten entfernten Branches bereinigen Sie veraltete Referenzen:

git fetch --prune

Um dies zum Standard zu machen:

git config --global fetch.prune true

Wenn Push langsam ist

Die Push-Geschwindigkeit hängt davon ab, wie viele neue Objektdaten Sie senden, wie teuer die lokale Packung ist, ob Hooks ausgeführt werden und wie schnell der entfernte Server das Pack akzeptiert.

Überprüfen Sie, ob Sie versehentlich große Dateien committet haben:

git rev-list --objects --all | sort -k 2 | tail

Dieser Befehl ist grob, da er keine Größen anzeigt. Für eine tiefere Inspektion verwenden Sie Tools wie git-sizer oder git filter-repo Analysebefehle, falls verfügbar. Der praktische Punkt ist einfach: Wenn ein Video, ein Datenbank-Dump, ein Archiv oder ein Build-Artefakt in die Historie gelangt ist, kann jeder Clone dafür bezahlen, bis die Historie umgeschrieben wird oder das Projekt zu einem besseren Speichermuster wechselt.

Git LFS ist die übliche Antwort für große binäre Assets, die zum Projekt gehören, aber nicht als normale Git-Blobs leben sollten:

git lfs install
git lfs track "*.psd"
git lfs track "*.mp4"
git add .gitattributes

Git LFS hilft am meisten, wenn es vor dem Eintritt großer Dateien in die Historie übernommen wird. Die Migration vorhandener Historie ist möglich, aber sie schreibt Commits um und erfordert Teamkoordination.

Seien Sie vorsichtig mit alten Ratschlägen, http.postBuffer zu erhöhen. Es wird oft für Push-Probleme vorgeschlagen, behebt aber selten allgemeine Langsamkeit in modernem Git. Wenn Pushes mit bestimmten HTTP-Fehlern fehlschlagen, überprüfen Sie den genauen Fehler, Proxy, Serverlimits und die Git-Version, bevor Sie zufällige Puffereinstellungen anwenden.

Repository-Wartung: git gc, Commit-Graphen und Repack

Git speichert Objekte in Packfiles. Im Laufe der Zeit können lokale Repositories lose Objekte und ineffiziente Packs ansammeln. Git führt die Wartung in vielen Workflows automatisch durch, aber manuelle Wartung kann älteren oder viel genutzten Repositories immer noch helfen.

Beginnen Sie mit einem sicheren Wartungsbefehl:

git maintenance run

Oder den älteren Befehl:

git gc

Vermeiden Sie es, git gc --prune=now als Ihren ersten Schritt zu machen. Das sofortige Entfernen unerreichbarer Objekte kann dazu führen, dass diese nicht mehr wiederherstellbar sind. Es kann in Ordnung sein, wenn Sie wissen, was Sie tun, aber es ist kein harmloser Geschwindigkeitsknopf.

Für Repositories mit großen Historien können Commit-Graphen die Historienwanderungen verbessern, die von Befehlen wie log, merge-base und fetch negotiation verwendet werden:

git commit-graph write --reachable

Moderne Git-Wartung kann dies für Sie erledigen. Überprüfen Sie Ihre Version:

git --version

Git aktuell zu halten, ist eine der am wenigsten dramatischen Leistungsverbesserungen. Neuere Versionen verbessern regelmäßig Sparse Checkout, partiellen Clone, Dateisystemüberwachung und Wartungsverhalten.

Große Repositories und Monorepos

Wenn ein Repository langsam ist, weil es wirklich groß ist, helfen lokale Anpassungen nur begrenzt. Sie benötigen Workflow-Änderungen.

Für binärlastige Repositories verschieben Sie große Assets zu Git LFS oder einem Artefakt-Store. Für generierte Dateien hören Sie auf, Ausgaben zu committen, die neu erstellt werden können. Für Monorepos verwenden Sie Sparse Checkout und Build-Tools, die Projektgrenzen verstehen. Für CI vermeiden Sie vollständige Clones, es sei denn, der Job benötigt die vollständige Historie.

Eine nützliche Monorepo-Einrichtung für einen Entwickler, der an einem Dienst arbeitet, könnte sein:

git clone --filter=blob:none --sparse <url>
cd repo
git sparse-checkout set services/billing packages/common

Eine nützliche CI-Einrichtung für einen einfachen Testjob könnte sein:

git fetch --depth 50 origin main

Die richtige Tiefe hängt vom Job ab. Wenn Ihr Versionierungstool Tags von vor Monaten verwendet, wird eine Tiefe von 1 es zerstören.

Hooks und externe Tools

Git ist möglicherweise nicht der langsame Teil. Ein pre-commit-Hook kann Formatierer, Linter, Tests, Secret-Scans oder Abhängigkeitsprüfungen ausführen. Ein post-checkout-Hook kann Dateien neu erstellen. Ein Credential-Helper kann pausieren, während er versucht, einen Schlüsselbund zu entsperren.

Überprüfen Sie Hooks:

git config --get core.hooksPath
ls -l .git/hooks .githooks 2>/dev/null

Vergleichen Sie vorübergehend mit deaktivierten Hooks, nur wenn Sie das Risiko verstehen:

git commit --no-verify

Für Nicht-Commit-Befehle verschieben oder deaktivieren Sie den Hook in einer Testkopie des Repositories, anstatt Team-Hooks aus Ihrem Haupt-Checkout zu löschen.

Wenn eine IDE Git langsam macht, das Terminal aber schnell ist, überprüfen Sie die IDE-Git-Integrationen. Einige Tools führen git status wiederholt aus, scannen unverfolgte Dateien oder aktualisieren den Branch-Status im Hintergrund.

Netzwerk- und Remote-Prüfungen

Trennen Sie für Remote-Operationen Git vom Netzwerkpfad. Versuchen Sie:

GIT_TRACE_PERFORMANCE=1 git ls-remote <url>
GIT_TRACE_PERFORMANCE=1 git fetch

Wenn git ls-remote langsam ist, tritt die Verzögerung auf, bevor viele Repository-Daten übertragen werden. Denken Sie an DNS, Proxy, VPN, SSH-Authentifizierung, Remote-Verfügbarkeit oder Credential-Prompts. Wenn ls-remote schnell ist, aber Fetch langsam ist, sind Repository-Datengröße und Verhandlung wahrscheinlicher.

Für SSH-Remotes testen Sie SSH direkt:

ssh -T [email protected]

Verwenden Sie Ihren tatsächlichen Git-Host. Für HTTPS-Remotes können Credential-Manager-Prompts hinter GUI-Fenstern versteckt sein. Ein gestoppter Fetch wartet möglicherweise auf die Authentifizierung.

Ein kurzer Entscheidungsbaum

Wenn git status langsam ist, überprüfen Sie unverfolgte Dateien, generierte Verzeichnisse, Antivirensoftware, Cloud-Synchronisationsordner, Dateisystem-Monitor und Indexeinstellungen.

Wenn Clone langsam ist, ziehen Sie flachen Clone, partiellen Clone, Sparse Checkout, Git LFS in Betracht und ob die Repository-Historie große Blobs enthält.

Wenn Fetch langsam ist, bereinigen Sie veraltete Referenzen, aktualisieren Sie Git, überprüfen Sie Netzwerk-Traces und ob das Remote viele Branches oder Tags hat.

Wenn Push langsam ist, suchen Sie nach großen neuen Objekten, langsamen Hooks, serverseitigen Prüfungen und Netzwerk- oder Proxy-Problemen.

Wenn alle Git-Befehle langsam sind, überprüfen Sie die Festplattengesundheit, freien Speicherplatz, Sicherheitssoftware, Git-Version und ob das Repository auf einem Netzwerkmount liegt.

Die beste Lösung ist die, die zum gemessenen Engpass passt. Git-Performance-Arbeit wird chaotisch, wenn alle Vorschläge auf einmal angewendet werden. Ändern Sie eine Sache, messen Sie erneut und behalten Sie die Änderung nur, wenn sie tatsächlich hilft.

Team-Level-Fixes schlagen persönliche Anpassungen

Wenn nur ein Entwickler langsames Git hat, sind lokale Einstellungen und Maschinengesundheit gute Ausgangspunkte. Wenn alle langsames Git haben, muss das Repository Aufmerksamkeit bekommen. Persönliche Anpassungen werden den Schmerz eine Weile verbergen, aber neue Entwickler und CI-Jobs werden weiterhin die Kosten tragen.

Suchen Sie nach großen Objekten, die nie hätten committet werden sollen, generierten Verzeichnissen, die in .gitignore gehören, und alten Branches, die unnötige Historie am Leben erhalten. Bevor Sie die Historie umschreiben, sprechen Sie mit dem Team. Historie-Umschreibungen betreffen jeden Clone und jeden offenen Branch. Sie können sich lohnen, aber sie erfordern Koordination.

Für Repositories mit legitimen großen Assets definieren Sie eine Richtlinie, anstatt sich auf das Gedächtnis zu verlassen. Zum Beispiel: Quellcode in Git, Design-Exporte in Git LFS, Build-Artefakte im Artefakt-Repository, Datenbank-Dumps in kontrolliertem Speicher und lokale temporäre Dateien ignoriert. Legen Sie diese Regeln in .gitattributes und .gitignore fest, damit Git die Form des Repositories durchsetzen kann.

CI verdient eine eigene Überprüfung. Viele Pipelines klonen die vollständige Historie, weil es die Standardeinstellung war, die vor Jahren kopiert wurde. Wenn der Job nur Unit-Tests ausführt, benötigt er möglicherweise nicht alle Tags und alle Branches. Wenn der Job eine Version erstellt, benötigt er möglicherweise Tags, aber nicht jeden Blob in einem Monorepo. Messen Sie die Clone-Zeit getrennt von der Build-Zeit, damit die Repository-Kosten sichtbar sind.

Ein einfaches CI-Audit fragt:

Benötigt dieser Job die vollständige Historie?
Benötigt er Tags?
Benötigt er jedes Submodul?
Benötigt er jedes Verzeichnis im Monorepo?
Ruft er LFS-Dateien ab, die er nie liest?

Diese ehrlich zu beantworten, spart oft mehr Zeit als das Optimieren obskurer Git-Optionen.

Dokumentieren Sie schließlich den empfohlenen Clone-Befehl für das Projekt. Wenn neue Entwickler partiellen Clone und Sparse Checkout verwenden sollten, sagen Sie das in der README. Wenn sie Git LFS vor dem Checkout benötigen, sagen Sie das auch. Leistungsrichtlinien, die nur in der Shell-Historie eines leitenden Entwicklers leben, helfen der nächsten Person nicht.