Git LFS: Grosse Dateien sinnvoll versionieren
git
HEAD
Git · LFS · Binärdateien · Repository-Hygiene
Git LFS
Grosse Dateien sinnvoll versionieren

Wer PSD-Dateien, Videos oder Archive direkt in Git committet, bläht die Repository-Grösse und die Clone-Zeit für das ganze Team unnötig auf, weil Gits Delta-Kompression bei Binärdaten kaum greift. Git LFS ersetzt diese Dateien durch schlanke Pointer und lagert die eigentlichen Inhalte extern, ohne dass sich am gewohnten Commit- und Push-Workflow etwas ändert.

13 Min. Lesezeit git lfs track · Pointer-Dateien · git lfs migrate Git 2.x · GitHub · GitLab

1. Warum Git bei grossen Binärdateien an seine Grenzen stösst

Gits Speichermodell ist für Quelltext optimiert. Bei jedem Commit berechnet Git intern Deltas zwischen Textzeilen und speichert Objekte hochkomprimiert, weil sich Textänderungen zeilenweise gut vergleichen lassen. Bei einer PSD-Datei, einem Video oder einem ZIP-Archiv funktioniert diese Diff-Logik praktisch nicht: Schon eine einzelne geänderte Pixelzeile oder ein neu berechneter Kompressions-Header führt dazu, dass die komplette Binärdatei als neues, vollständiges Objekt in die Historie geschrieben wird. Es gibt keine sinnvolle Zeilenstruktur, an der Git ansetzen könnte.

Die Folge summiert sich schnell: Fünfzig Versionen einer 100-Megabyte-Design-Datei bedeuten fünf Gigabyte reine Historiendaten, selbst wenn im Arbeitsverzeichnis nur die aktuelle Version sichtbar ist. Da Git-Historie standardmässig unveränderlich ist, bleibt jede jemals committete Version für immer im Repository, auch nach dem Löschen der Datei im aktuellen Stand. Jeder git clone lädt diese gesamte Historie herunter, was Onboarding neuer Teammitglieder, CI-Pipelines und einfache Backups spürbar verlangsamt und den verfügbaren Speicherplatz auf Git-Hosting-Plattformen unnötig belastet.

2. Wie Git LFS technisch funktioniert: Pointer-Dateien und Smudge/Clean-Filter

Git LFS (Large File Storage) löst dieses Problem, indem es den eigentlichen Binärinhalt nicht mehr im Git-Objektspeicher ablegt, sondern durch eine winzige Pointer-Datei ersetzt. Diese Textdatei landet an derselben Stelle in der Git-Historie wie zuvor die Binärdatei, ist aber nur wenige Bytes gross und enthält lediglich Versionsangabe, den SHA-256-Hash des Inhalts (oid) und dessen Dateigrösse. Der tatsächliche Binärinhalt wird stattdessen auf einem separaten LFS-Server gespeichert, den GitHub, GitLab oder eine selbst betriebene Instanz bereitstellen.

Damit dieser Austausch transparent bleibt, registriert Git LFS zwei Git-Filter: den clean filter, der beim git add/git commit die Binärdatei durch ihre Pointer-Repräsentation ersetzt und den Inhalt in einen lokalen LFS-Cache sowie beim Push zum Server hochlädt, und den smudge filter, der beim Checkout die umgekehrte Richtung übernimmt und die Pointer-Datei automatisch wieder durch den echten Binärinhalt ersetzt. Für Entwickler ist dieser Mechanismus unsichtbar: Im Arbeitsverzeichnis erscheint immer die vollständige Datei, während Git selbst nur die schlanke Pointer-Version verwaltet.


# What actually gets stored in the Git history instead of the binary blob:
cat assets/hero-banner.psd

# version https://git-lfs.github.com/spec/v1
# oid sha256:4d7a2c8e9f1b3a6d5c8e0f2a1b4c7d9e6f3a2b5c8d1e4f7a0b3c6d9e2f5a8b1c
# size 157286400

# Locally, "git lfs" resolves the pointer back into the real file
git lfs pointer --file=assets/hero-banner.psd

3. Installation und Ersteinrichtung von Git LFS

Git LFS ist kein Bestandteil von Git selbst, sondern ein separates Client-Tool, das zusätzlich installiert werden muss, etwa über apt install git-lfs, brew install git-lfs oder das offizielle Installationspaket. Nach der Installation aktiviert git lfs install die notwendigen Git-Filter global im Nutzerprofil, sodass jedes neu geklonte oder initialisierte Repository auf dieser Maschine die filter=lfs-Direktiven aus .gitattributes automatisch erkennt und anwendet. Dieser Schritt muss pro Maschine nur einmal ausgeführt werden, nicht pro Repository.

Für Fälle, in denen die globalen Filter bewusst nicht gesetzt werden sollen, etwa auf einem CI-Runner mit eingeschränkten Rechten, existiert git lfs install --local, das die Filter nur in der lokalen .git/config des aktuellen Repositories registriert. git lfs version bestätigt, dass sowohl die LFS-Erweiterung als auch die zugrunde liegende Git-Version kompatibel sind, was insbesondere bei älteren CI-Images regelmässig zu Fehlern führt, wenn die Version stillschweigend fehlt.


# Install the git-lfs client (once per operating system / package manager)
sudo apt-get install git-lfs        # Debian/Ubuntu
brew install git-lfs                # macOS

# Register the Git filters globally for this user account, once per machine
git lfs install

# Register the filters only for the current repository (e.g. restricted CI runner)
git lfs install --local

# Verify the installed client and Git compatibility
git lfs version

4. Dateitypen tracken mit git lfs track und .gitattributes

Welche Dateien über LFS verwaltet werden, legt git lfs track fest. Der Befehl git lfs track "*.psd" schreibt eine entsprechende Zeile mit den Attributen filter=lfs diff=lfs merge=lfs -text in die Datei .gitattributes im Repository-Root. Diese Attribute weisen Git an, für passende Dateien die LFS-Filter zu verwenden und sie als Binärdaten zu behandeln, ohne Zeilenenden zu normalisieren. Patterns lassen sich beliebig kombinieren, etwa für ganze Verzeichnisse mit assets/videos/**/*.mp4 oder für mehrere Dateitypen gleichzeitig in separaten track-Aufrufen.

Der entscheidende, oft übersehene Schritt: Die .gitattributes-Datei selbst muss ganz normal mit git add .gitattributes und git commit versioniert werden. Nur so greifen dieselben Tracking-Regeln bei jedem Teammitglied, das das Repository klont. Wird die Datei vergessen, legt zwar der ursprüngliche Autor seine Dateien korrekt über LFS ab, jeder andere Klon behandelt neue Binärdateien desselben Typs aber wieder als gewöhnliche, direkt in der Historie gespeicherte Blobs.


# .gitattributes - generated and extended via "git lfs track"
*.psd filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text
assets/videos/**/*.mov filter=lfs diff=lfs merge=lfs -text

# List every pattern currently tracked by Git LFS in this repository
# git lfs track

5. Der Workflow im Alltag: Commit, Push, Clone mit LFS

Nach der Ersteinrichtung ändert sich am gewohnten Ablauf mit git add, git commit und git push nichts sichtbar. Im Hintergrund erkennt Git anhand der .gitattributes-Regeln automatisch, welche Dateien über LFS laufen, ersetzt sie beim Commit durch Pointer und lädt die eigentlichen Inhalte beim Push separat zum LFS-Endpunkt hoch. git lfs ls-files zeigt zuverlässig, welche Dateien im aktuellen Commit tatsächlich als LFS-Objekte verwaltet werden, während git lfs status zusätzlich anzeigt, ob lokale LFS-Dateien bereits hochgeladen wurden oder noch ausstehen.

Beim Klonen lädt Git standardmässig nur die Pointer-Dateien sofort mit herunter; die zugehörigen Binärinhalte werden erst beim Checkout über den Smudge-Filter nachgezogen, was den initialen git clone spürbar beschleunigt. Wichtig für die Praxis: GitHub und GitLab begrenzen LFS-Speicher und -Bandbreite getrennt vom regulären Repository-Kontingent, mit vergleichsweise kleinen kostenlosen Freikontingenten, die bei aktiven Design- oder Video-Repositories schnell ausgeschöpft sind und dann kostenpflichtige Erweiterungen erfordern.


# Clone downloads pointers immediately, binary content follows on checkout
git clone https://git.example.com/team/shop.git

# List which files in the current commit are actually managed as LFS objects
git lfs ls-files
# 4d7a2c8e * assets/hero-banner.psd
# 9b3f1e0a * assets/videos/teaser.mp4

# Show which LFS files are staged, modified, or still pending upload
git lfs status

6. Bestehende grosse Dateien nachträglich migrieren mit git lfs migrate

Tracking-Regeln über git lfs track wirken nur auf künftige Commits. Binärdateien, die bereits vor der LFS-Einführung in die Historie eingecheckt wurden, bleiben davon unberührt und blähen das Repository weiterhin auf. Für diesen Fall existiert git lfs migrate import, das die gesamte Commit-Historie durchläuft, alle passenden Blobs extrahiert, sie durch Pointer-Dateien ersetzt und die betroffenen Commits neu schreibt. Mit --include="*.psd" --everything lässt sich die Migration gezielt auf bestimmte Dateitypen über alle Branches hinweg anwenden.

Weil dabei jeder betroffene Commit eine neue Prüfsumme erhält, ändert sich effektiv die gesamte nachfolgende Historie, und ein einfaches git push reicht danach nicht mehr aus, sondern erfordert git push --force-with-lease. Vor einer solchen Migration ist ein vollständiges Backup des Repositories Pflicht, da der Vorgang destruktiv ist und sich nicht ohne Weiteres rückgängig machen lässt. Genauso wichtig ist die Koordination im Team: Alle Mitarbeitenden müssen nach dem Force-Push ihre lokalen Kopien neu klonen oder ihre Branches gezielt auf den neuen Verlauf umbasieren, sonst entstehen doppelte, widersprüchliche Historien.


# Always create a full backup/mirror before rewriting history
git clone --mirror https://git.example.com/team/shop.git shop-backup.git

# Rewrite history: replace already-committed .psd files with LFS pointers
git lfs migrate import --include="*.psd" --everything

# Push the rewritten history; regular push is rejected due to changed hashes
git push --force-with-lease origin --all
git push --force-with-lease origin --tags

# Every teammate must re-clone or reset onto the rewritten history
# git fetch origin && git reset --hard origin/main

7. Grenzen und Stolperfallen von Git LFS

Git LFS verschiebt das Speicherproblem, statt es vollständig aufzulösen: Auf gängigen Hosting-Plattformen wird LFS-Speicher und -Bandbreite separat abgerechnet und ist bereits im Basis-Plan oft knapp bemessen. Bei grossen Asset-Bibliotheken mit häufigen Änderungen können diese Kosten schnell steigen, insbesondere weil jede neue Version einer Binärdatei als vollständig neues LFS-Objekt gespeichert wird und keine Delta-Kompression zwischen Versionen stattfindet. Ausserdem hilft LFS nur dort, wo es aktiv eingerichtet wurde: Ohne eine nachträgliche Migration bleiben historisch bereits committete Binärdateien unverändert im normalen Git-Objektspeicher liegen.

Wer LFS nicht bei einem grossen Hosting-Anbieter, sondern selbst betreiben möchte, kann auf einen eigenen LFS-Server setzen; viele selbstgehostete Git-Plattformen wie GitLab CE oder Gitea bringen LFS-Unterstützung bereits eingebaut mit. Als leichtgewichtige Ergänzung, wenn eine vollständige LFS-Infrastruktur nicht gewünscht ist, eignet sich ausserdem Partial Clone (git clone --filter=blob:none), das grosse Blobs erst bei tatsächlichem Zugriff nachlädt, ohne dass dafür ein separater LFS-Server nötig wäre.

8. Alternativen und Ergänzungen zu Git LFS

git-annex verfolgt einen ähnlichen Grundgedanken wie Git LFS, ist aber deutlich flexibler und komplexer: Es unterstützt beliebige Speicher-Backends, verschlüsselte Remotes und feingranulare Kontrolle darüber, welche Dateien lokal tatsächlich vorliegen. Für Teams, die primär ein einfaches, weit verbreitetes Tool suchen, ist der zusätzliche Lernaufwand meist nicht gerechtfertigt. Eine andere Ergänzung sind Git-Submodule, mit denen grosse Asset-Sammlungen in ein eigenes Repository ausgelagert und nur bei Bedarf eingebunden werden, sowie DVC (Data Version Control), das speziell für ML-Datensätze und -Pipelines entwickelt wurde und Versionierung mit Experiment-Tracking kombiniert.

Ebenso wichtig ist die Frage, wann LFS die falsche Antwort ist. Generierte oder importierte Medien, etwa Magento-Produktbilder in pub/media/, gehören grundsätzlich gar nicht in ein Git-Repository, unabhängig davon, ob mit oder ohne LFS. Solche Assets werden über Datenbank-Importe, S3-Buckets oder CDN-Deployments verwaltet, während Git für Quellcode und klar abgegrenzte, versionierungswürdige Design-Assets reserviert bleibt. Git LFS ist ein Werkzeug für Dateien, die tatsächlich Teil der Entwicklungshistorie sein sollen, nicht ein generischer Ersatz für Asset-Storage.

9. Git LFS im Vergleich: Patterns richtig vs. falsch angewendet

Die meisten Probleme mit Git LFS lassen sich auf wenige wiederkehrende Szenarien zurückführen, die sich durch den richtigen Ansatz jeweils vollständig vermeiden lassen. Die folgende Übersicht stellt typische Fehlentscheidungen der empfohlenen Strategie gegenüber.

Aufgabe Falsch Richtiges Pattern Vorteil
Binärdateien einbinden, die schon committet sind Nur git lfs track ausführen git lfs migrate import --everything Historie wird tatsächlich verkleinert
Tracking-Regeln teamweit teilen .gitattributes lokal belassen .gitattributes committen und pushen Gleiche Regeln bei jedem Klon
Historie nach Migration verteilen Normaler git push git push --force-with-lease + Team-Ankündigung Keine widersprüchlichen Historien
Gemischte Assets im selben Repo Manche PSDs getrackt, andere nicht Ein Pattern pro Dateityp, konsequent Vorhersagbares Repository-Verhalten
Speicher- und Bandbreitenkosten planen Quotas erst bei Fehlermeldung prüfen LFS-Nutzung vorab im Hosting-Dashboard abschätzen Keine blockierten Pushes im Sprint

Die Tabelle zeigt ein durchgängiges Muster: Git LFS funktioniert zuverlässig, sobald Tracking-Regeln, Historie und Team-Kommunikation konsequent zusammenpassen. Die meisten Probleme entstehen nicht durch das Werkzeug selbst, sondern durch halb durchgeführte Einrichtung, etwa vergessene .gitattributes-Commits oder eine Migration ohne vorherige Abstimmung im Team.

Mironsoft

Git-Workflows, Repository-Hygiene und Deployment-Setup für PHP- und Magento-Teams

Repository durch grosse Binärdateien überlastet?

Wir richten Git LFS für euer Team ein, migrieren bestehende Binärdateien sicher aus der Historie und koordinieren den Force-Push, ohne dass Mitarbeitende ihre laufende Arbeit verlieren.

LFS-Einrichtung

Tracking-Regeln, .gitattributes und Team-Onboarding sauber aufsetzen

Historie-Migration

Sichere Migration bestehender Binärdateien mit Backup und Rollout-Plan

Kosten-Check

LFS-Speicher- und Bandbreitenbedarf realistisch einschätzen

10. Zusammenfassung

Git LFS löst ein konkretes strukturelles Problem: Binärdateien passen nicht zu Gits zeilenbasierter Delta-Kompression und blähen Repository und Clone-Zeit unnötig auf. Pointer-Dateien mit Versionsangabe, SHA-256-Hash und Dateigrösse ersetzen die eigentlichen Inhalte in der Git-Historie, während Smudge- und Clean-Filter den Austausch beim Checkout und Commit transparent im Hintergrund erledigen. git lfs track plus eine committete .gitattributes legen fest, welche Dateitypen betroffen sind, und der gewohnte Commit-Push-Workflow bleibt für Entwickler unverändert.

Für bereits bestehende Repositories ist git lfs migrate import der einzige Weg, historische Binärdateien tatsächlich aus der Vergangenheit zu entfernen, allerdings nur mit vollständigem Backup und abgestimmtem Force-Push im gesamten Team. Wer diese Schritte konsequent umsetzt und gleichzeitig weiss, wann Assets gar nicht erst ins Repository gehören, etwa generierte Magento-Medien, hält das Repository dauerhaft schlank und performant.

Git LFS: Grosse Dateien sinnvoll versionieren - Das Wichtigste auf einen Blick

Das Grundproblem

Gits Delta-Kompression funktioniert bei Text, nicht bei Binärdaten. Jede Version einer grossen Datei bläht die Historie dauerhaft auf.

Pointer + Filter

Eine kleine Pointer-Datei ersetzt den Binärinhalt in Git. Smudge- und Clean-Filter tauschen sie transparent beim Checkout/Commit aus.

Tracking einrichten

git lfs track "*.psd" plus committete .gitattributes, damit alle Teammitglieder dieselben Regeln nutzen.

Migration bestehender Dateien

git lfs migrate import --everything rewrites die Historie. Backup vorher, --force-with-lease danach, Team informieren.

11. FAQ: Git LFS

1Was ist Git LFS und wofür wird es eingesetzt?
Ersetzt grosse Binärdateien in der Git-Historie durch kleine Pointer und lagert die Inhalte auf einem separaten LFS-Server, ohne den gewohnten Workflow zu ändern.
2Wie sieht eine LFS-Pointer-Datei aus?
Wenige Bytes grosse Textdatei mit Versionsangabe, SHA-256-Hash (oid) und Dateigrösse, die den Binärinhalt in der Historie ersetzt.
3Was machen Smudge- und Clean-Filter genau?
Clean ersetzt beim Commit die Binärdatei durch einen Pointer und lädt hoch. Smudge macht beim Checkout das Gegenteil und stellt den echten Inhalt wieder her.
4Muss ich Git LFS auf jedem Rechner neu installieren?
Der Client wird einmal pro Maschine installiert, git lfs install registriert die Filter danach global für alle Repositories auf diesem Rechner.
5Wie lege ich fest, welche Dateitypen über LFS laufen?
Mit git lfs track "*.psd", das eine Regel in .gitattributes schreibt. Diese Datei muss committet und gepusht werden, damit sie im Team greift.
6Was passiert, wenn ich vergesse, .gitattributes zu committen?
Andere Klone kennen die Regel nicht und behandeln neue Dateien wieder als normale Blobs. Ergebnis: inkonsistentes Verhalten im Team.
7Wie migriere ich bereits committete Binärdateien nachträglich in LFS?
Mit git lfs migrate import --include="*.psd" --everything. Vorher Backup, danach Force-Push nötig, da sich Commit-Hashes ändern.
8Warum reicht nach einer Migration kein normaler git push?
Migration erzeugt neue Commit-Hashes, Git erkennt divergierende Historie. Nötig ist git push --force-with-lease plus Team-Ankündigung.
9Kostet Git LFS auf GitHub oder GitLab extra?
Ja, LFS-Speicher und -Bandbreite werden meist separat und mit kleinem Freikontingent abgerechnet. Aktive Repos brauchen oft kostenpflichtige Erweiterungen.
10Sollten Magento-Produktbilder über Git LFS versioniert werden?
In der Regel nicht. Generierte/importierte Medien gehören unabhängig von LFS nicht ins Repository, sondern in Datenbank-Importe, S3 oder CDN-Deployments.