Git LFS

Git LFS

Was ist Git LFS?

Git ist ein verteiltes Versionskontrollsystem, d. h. der gesamte Repository-Verlauf wird während des Klonvorgangs auf den Client übertragen. Bei Projekten mit großen Dateien, insbesondere bei großen Dateien, die regelmäßig bearbeitet werden, kann dieser anfängliche Klon enorm viel Zeit in Anspruch nehmen, da jede Version jeder Datei vom Client heruntergeladen wird. Git LFS (Large File Storage) ist eine Git-Erweiterung von Atlassian, GitHub und einigen anderen an Open-Source-Projekten Mitwirkenden. Das Tool reduziert die Auswirkungen großer Dateien in deinem Repository, indem die relevanten Versionen per Lazy Loading heruntergeladen werden. Genauer gesagt, große Dateien werden während dem Checkout-Prozess statt während des Klonens oder Abrufens heruntergeladen.

Dies erfolgt in Git LFS durch das Ersetzen großer Dateien in deinem Repository mit winzigen Pointer-Dateien. Während der normalen Nutzung wirst du diese Pointer-Dateien nie zu Gesicht bekommen, da diese von Git LFS automatisch verarbeitet werden:

  1. Wenn du deinem Repository eine Datei hinzufügst, ersetzt Git LFS die Inhalte mit einem Pointer und speichert die Dateiinhalte in einem lokalen Git LFS-Cache. 

    git lfs - git add
  2. Wenn du neue Commits zum Server pushst, werden alle Git LFS-Dateien, die von den neu gepushten Commits referenziert werden, von deinem lokalen Git LFS-Cache an den mit deinem Git-Repository verbundenen Git LFS-Remote-Speicher übertragen. 

    git lfs - git push
  3. Wenn du einen Commit auscheckst, der Git LFS Pointers enthält, werden diese mit Dateien aus deinem lokalen Git LFS-Cache ersetzt oder vom Git LFS-Remote-Speicher heruntergeladen. git lfs - git checkout

Git LFS ist nahtlos: In deiner Arbeitskopie siehst du nur deinen tatsächlichen Dateiinhalt. Aus diesem Grund kannst du Git LFS nutzen, ohne deinen bestehenden Git-Workflow zu ändern. Du arbeitest einfach wie immer mit den Befehlen git checkout, edit, git add und git commit. git clone und git pull werden erheblich schneller ausgeführt, wenn du nur die Versionen großer Dateien herunterlädst, die von den Commits referenziert werden, die du tatsächlich auscheckst, anstatt jeder Version der Datei, die jemals existiert hat.

Für Git LFS brauchst du einen Git-LFS-fähigen Host, wie etwa Bitbucket Cloud oder Bitbucket Server. Repository-Benutzer müssen den Befehlszeilen-Client für Git LFS installiert haben oder einen Git-LFS-fähigen GUI-Client wie SourceTree verwenden. Übrigens: Steve Streeting, der Atlassian-Entwickler von SourceTree, beteiligt sich auch intensiv am Git-LFS-Projekt. Daher sind SourceTree und Git LFS gut miteinander kompatibel.

Was ist Git LFS?

Installieren von Git LFS

  1. Es gibt drei einfache Möglichkeiten zur Installation von Git LFS:

    a. Installiere es mit deinem bevorzugten Paketmanager. git-lfs-Pakete sind verfügbar für Homebrew, MacPorts, dnf und packagecloud.

    b. Lade Git LFS von der Projekt-Webseite herunter und installiere es.

    c. Installiere SourceTree, einen kostenlosen GUI-Client für Git, der zusammen mit Git LFS erhältlich ist.

  2. Führe nach dem Initialisieren von Git LFS den Befehl "git lfs install" aus (wenn du SourceTree installiert hast, kannst du diesen Schritt überspringen):

    $ git lfs install
    Git LFS initialized.
    

    Du musst git lfs install nur einmal ausführen. Sobald Git LFS für dein System initialisiert ist, wird es automatisch geladen, wenn du ein Repository mit Git LFS-Inhalten klonst.

Erstellen eines neuen Git LFS-Repositorys

Wenn ein neues Repository mit Git LFS kompatibel sein soll, musst du nach dem Erstellen des Repositorys "git lfs install" ausführen.

# initialize Git
$ mkdir Atlasteroids
$ cd Atlasteroids
$ git init
Initialized empty Git repository in /Users/tpettersen/Atlasteroids/.git/
# initialize Git LFS
$ git lfs install
Updated pre-push hook.
Git LFS initialized.

Hiermit wird ein spezieller pre-push-Git Hook in deinem Repository installiert, der Git LFS-Dateien an den Server überträgt, wenn du git push ausführst.

Git LFS wird automatisch für alle Bitbucket Cloud-Repositorys aktiviert. Für Bitbucket Server musst du Git LFS in den Einstellungen deines Repositorys aktivieren:

Git LFS in Bitbucket Server

Sobald Git LFS für dein Repository initialisiert ist, kannst du mit git lfs track festlegen, welche Dateien verfolgt werden sollen.

Klonen eines bestehenden Git LFS-Repositorys

Nachdem Git LFS installiert ist, kannst du Git LFS-Repositorys ganz normal mit git clone klonen. Am Ende des Klonprozesses wird Git den Standard-Branch auschecken (normalerweise den master) und alle Git LFS-Dateien, die zum Abschluss des Checkout-Prozesses benötigt werden, werden automatisch für dich heruntergeladen. Ein Beispiel:

$ git clone git@bitbucket.org:tpettersen/Atlasteroids.git
Cloning into 'Atlasteroids'...
remote: Counting objects: 156, done.
remote: Compressing objects: 100% (154/154), done.
remote: Total 156 (delta 87), reused 0 (delta 0)
Receiving objects: 100% (156/156), 54.04 KiB | 31.00 KiB/s, done.
Resolving deltas: 100% (87/87), done.
Checking connectivity... done.
Downloading Assets/Sprites/projectiles-spritesheet.png (21.14 KB)
Downloading Assets/Sprites/productlogos_cmyk-spritesheet.png (301.96 KB)
Downloading Assets/Sprites/shuttle2.png (1.62 KB)
Downloading Assets/Sprites/space1.png (1.11 MB)
Checking out files: 100% (81/81), done.

In diesem Repository befinden sich vier PNGs, die von Git LFS verfolgt werden. Beim Ausführen von "git clone", werden Git LFS-Dateien einzeln nacheinander heruntergeladen, während Pointer-Dateien aus deinem Repository ausgecheckt werden.

Beschleunigen von Klonen

Wenn du ein Repository mit einer großen Anzahl von Dateien klonst, bietet der Befehl git lfs clone eine deutlich bessere Leistung:

$ git lfs clone git@bitbucket.org:tpettersen/Atlasteroids.git
in "Atlasteroids"...
remote: Counting objects: 156, done.
remote: Compressing objects: 100% (154/154), done.
remote: Total 156 (delta 87), reused 0 (delta 0)
Receiving objects: 100% (156/156), 54.04 KiB | 0 bytes/s, done.
Resolving deltas: 100% (87/87), done.
Checking connectivity... done.
Git LFS: (4 of 4 files) 1.14 MB / 1.15 MB

Anstatt die Git LFS-Dateien einzeln herunterzuladen, wird beim Befehl git lfs clone gewartet, bis der Checkout abgeschlossen ist, und anschließend werden alle benötigten Git LFS-Dateien im Batch heruntergeladen. Hierbei werden parallelisierte Downloads genutzt und die Anzahl der ausgelösten HTTP-Anfragen und Prozesse sinkt drastisch (dies ist insbesondere zur Leistungsverbesserung in Windows von Bedeutung).

Durchführen von Pulls und Checkouts

Genau wie beim Klonen kannst du mit einem normalen git pull-Befehl einen Pull von einem Git LFS-Repository durchführen. Alle benötigten Git LFS-Dateien werden im Rahmen des automatischen Checkout-Prozesses heruntergeladen, sobald der Pull abgeschlossen ist.

$ git pull
Updating 4784e9d..7039f0a
Downloading Assets/Sprites/powerup.png (21.14 KB)
Fast-forward
Assets/Sprites/powerup.png | 3 +
Assets/Sprites/powerup.png.meta | 4133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 4136 insertions(+)
create mode 100644 Assets/Sprites/projectiles-spritesheet.png
create mode 100644 Assets/Sprites/projectiles-spritesheet.png.meta

Zum Abrufen von Git LFS-Inhalten werden keine expliziten Befehle benötigt. Sollte der Checkout jedoch unerwartet fehlschlagen, kannst du für den aktuellen Commit fehlende Git LFS-Inhalte mit git lfs pull herunterladen:

$ git lfs pull
Git LFS: (4 of 4 files) 1.14 MB / 1.15 MB

Beschleunigen von Pulls

Wie git lfs clone lädt git lfs pull deine Git LFS-Dateien im Batch herunter. Wenn du weißt, dass sich seit dem letzten Pull ein große Anzahl an Dateien geändert hat, solltest du ggf. den automatischen Git LFS-Download während des Checkouts deaktivieren und dann deinen Git LFS-Inhalt mit einem expliziten git lfs pull-Befehl im Batch herunterladen. Hierzu setzt du dein Git config mit der Option -c außer Kraft, wenn du git pull ausführst:

$ git -c filter.lfs.smudge= -c filter.lfs.required=false pull && git lfs pull

Da die Eingabe hiervon recht mühselig ist, kannst du zum Durchführen eines Batch-Downloads und eines Git LFS-Pulls einen einfachen Git alias erstellen:

$ git config --global alias.plfs "\!git -c filter.lfs.smudge= -c filter.lfs.required=false pull && git lfs pull"
$ git plfs

Dies verbessert die Leistung erheblich, wenn eine große Anzahl an Git LFS-Dateien heruntergeladen werden muss (auch hier insbesondere bei Windows).

Verfolgen von Dateien mit Git LFS

Wenn du deinem Repository einen neuen Dateityp großer Dateien hinzufügst, musst du Git LFS mit dem Befehl git lfs track anweisen, diese nach einem bestimmten Muster zu verfolgen:

$ git lfs track "*.ogg"
Tracking *.ogg

Beachte, dass die Anführungszeichen um "*.ogg" wichtig sind. Wenn du sie vergisst, wird die Wildcard von der Shell erweitert und für jede .ogg-Datei in deinem aktuellen Verzeichnis werden eigene Einträge erstellt.

# probably not what you want
$ git lfs track *.ogg
Tracking explode.ogg
Tracking music.ogg
Tracking phaser.ogg

Die von Git LFS unterstützten Muster sind dieselben, die auch von .gitignore unterstützt werden, z. B.:

# track all .ogg files in any directory
$ git lfs track "*.ogg"
# track files named music.ogg in any directory
$ git lfs track "music.ogg"
# track all files in the Assets directory and all subdirectories
$ git lfs track "Assets/"
# track all files in the Assets directory but *not* subdirectories
$ git lfs track "Assets/*"
# track all ogg files in Assets/Audio
$ git lfs track "Assets/Audio/*.ogg"
# track all ogg files in any directory named Music
$ git lfs track "**/Music/*.ogg"
# track png files containing "xxhdpi" in their name, in any directory
$ git lfs track "*xxhdpi*.png

Diese Muster hängen von dem Verzeichnis ab, in dem du den Befehl git lfs track ausgeführt hast. Der Einfachheit halber solltest du git lfs track von der Root deines Repositorys aus ausführen. Beachte, dass Git LFS keine negativen Muster unterstützt, auch wenn dies bei .gitignore der Fall ist.

Nach dem Ausführen von git lfs track wirst du in dem Verzeichnis, von dem aus du den Befehl ausgeführt hast, eine neue Datei namens .gitattributes finden. .gitattributes ist ein Git-Mechanismus zum Binden spezieller Verhaltensmuster an bestimmte Dateimuster. Git LFS erstellt oder aktualisiert .gitattributes-Dateien automatisch, um die Muster verfolgter Dateien an den Git LFS-Filter zu binden. Änderungen an der .gitattributes-Datei musst du jedoch selbst an dein Repository committen:

$ git lfs track "*.ogg"
Tracking *.ogg
$ git add .gitattributes
$ git diff --cached
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..b6dd0bb
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.ogg filter=lfs diff=lfs merge=lfs -text
$ git commit -m "Track ogg files with Git LFS"

Zur leichteren Pflege ist es sinnvoll, alle Git LFS-Muster in einer einzigen .gitattributes-Datei zu sammeln, indem du git lfs track immer von der Root deines Repositorys aus ausführst. Du kannst dir jedoch eine Liste aller Muster, die derzeit von Git LFS verfolgt werden (und die .gitattributes-Dateien, in denen sie definiert sind), anzeigen lassen, indem du git lfs track ohne zusätzliche Argumente ausführst:

$ git lfs track
Listing tracked paths
*.stl (.gitattributes)
*.png (Assets/Sprites/.gitattributes)
*.ogg (Assets/Audio/.gitattributes)

Du kannst die Verfolgung eines bestimmten Musters durch Git LFS beenden, indem du einfach die entsprechende Zeile aus deiner .gitattributes-Datei entfernst oder den Befehl git lfs untrack ausführst:

$ git lfs untrack "*.ogg"
Untracking *.ogg
$ git diff
diff --git a/.gitattributes b/.gitattributes
index b6dd0bb..e69de29 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1 +0,0 @@
-*.ogg filter=lfs diff=lfs merge=lfs -text

Nach dem Ausführen von git lfs untrack musst du die Änderungen an .gitattributes manuell committen.

Durchführen von Commits und Pushes

Du kannst zu einem Repository mit Git LFS-Inhalten ganz normal committen und pushen. Wenn du Änderungen an Dateien committet hast, die von Git LFS verfolgt werden, wird dir eine zusätzliche Ausgabe von git push angezeigt, da die Git LFS-Inhalte zum Server übertragen werden:

$ git push
Git LFS: (3 of 3 files) 4.68 MB / 4.68 MB
Counting objects: 8, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (8/8), 1.16 KiB | 0 bytes/s, done.
Total 8 (delta 1), reused 0 (delta 0)
To git@bitbucket.org:tpettersen/atlasteroids.git
7039f0a..b3684d3 master -> master

Wenn die Übertragung der LFS-Dateien aus irgendeinem Grund fehlschlägt, wird der Push abgebrochen und du kannst es einfach erneut versuchen. Wie Git ist auch der Git-LFS-Speicher inhaltsadressiert: Zusammen mit den Inhalten wird ein Schlüssel abgespeichert, der ein SHA-256-Hash des Inhalts selbst ist. Ein erneuter Übertragungsversuch von Git-LFS-Dateien an den Server ist also immer sicher, da du die Inhalte einer Git-LFS-Datei nicht versehentlich mit der falschen Version überschreiben kannst.

Verschieben eines Git LFS-Repositorys zwischen Hosts

Zur Migration eines Git LFS-Repositorys von einem Hosting-Anbieter zu einem andren kannst du git lfs fetch und git lfs push zusammen mit der Option --all kombinieren.

So verschiebst du z. B. alle Git- and Git LFS-Repositorys von einem Remote namens github zu einem Remote namens bitbucket :

# create a bare clone of the GitHub repository
$ git clone --bare git@github.com:kannonboy/atlasteroids.git
$ cd atlasteroids
# set up named remotes for Bitbucket and GitHub
$ git remote add bitbucket git@bitbucket.org:tpettersen/atlasteroids.git
$ git remote add github git@github.com:kannonboy/atlasteroids.git
# fetch all Git LFS content from GitHub
$ git lfs fetch --all github
# push all Git and Git LFS content to Bitbucket
$ git push --mirror bitbucket
$ git lfs push --all bitbucket

Abrufen zusätzlicher Git LFS-Verlaufsinhalte

Git LFS lädt normalerweise nur die Dateien herunter, die für die tatsächlich lokal ausgecheckten Commits benötigst. Du kannst jedoch Git LFS mit git lfs fetch --recent zwingen, zusätzliche Inhalte für andere kürzlich modifizierte Branches herunterzuladen:

$ git lfs fetch --recent
Fetching master
Git LFS: (0 of 0 files, 14 skipped) 0 B / 0 B, 2.83 MB skipped Fetching recent branches within 7 days
Fetching origin/power-ups
Git LFS: (8 of 8 files, 4 skipped) 408.42 KB / 408.42 KB, 2.81 MB skipped
Fetching origin/more-music
Git LFS: (1 of 1 files, 14 skipped) 1.68 MB / 1.68 MB, 2.83 MB skipped

Dies ist hilfreich zum Herunterladen von neuen Git LFS-Inhalten in Batches, während du Mittagspause machst, oder wenn du Arbeitsresultate deiner Teamkollegen überprüfen möchtest und die Inhalte später aufgrund eingeschränkter Internetverbindung nicht mehr herunterladen kannst. Es ist beispielsweise sinnvoll, git lfs fetch --recent auszuführen, bevor du in ein Flugzeug steigst!

Git LFS betrachtet alle Branches oder Tags, die einen Commit enthalten, der neuer als sieben Tage ist als aktuell. Du kannst die Anzahl der Tage, für die Branches und Tags als aktuell gelten sollen, konfigurieren, indem du die Eigenschaft lfs.fetchrecentrefsdays entsprechend festlegst:

# download Git LFS content for branches or tags updated in the last 10 days
$ git config lfs.fetchrecentrefsdays 10

In den Standardeinstellungen wird git lfs fetch --recent nur Git LFS-Inhalte für den Commit an der Spitze des letzten Branch oder Tags herunterladen.

git lfs - git lfs fetch --recent

Du kannst jedoch Git LFS mit der Eigenschaft lfs.fetchrecentcommitsdays konfigurieren, damit Inhalte älterer Commits auf aktuellen Branches und Tags ebenfalls heruntergeladen werden.

# download the latest 3 days of Git LFS content for each recent branch or tag
$ git config lfs.fetchrecentcommitsdays 3

Verwende diese Einstellung mit Bedacht: Wenn sich deine Branches mit einer hohen Geschwindigkeit weiterentwickeln, kann dies dazu führen, dass eine riesige Datenmenge heruntergeladen wird. Sie kann jedoch nützlich sein, wenn du interstitielle Änderungen in einem Branch überprüfen, Commits gezielt aus verschiedenen Branches auswählen oder den Verlauf umschreiben möchtest.

git lfs - git lfs fetch --recent commits

Wie in Verschieben eines Git LFS-Repositorys zwischen Hosts erläutert, kannst du auch alle Git LFS-Inhalte deines Repositorys mit git lfs fetch --all abrufen:

$ git lfs fetch --all
Scanning for all objects ever referenced...
✔ 23 objects found
Fetching objects...
Git LFS: (9 of 9 files, 14 skipped) 2.06 MB / 2.08 MB, 2.83 MB skipped

Löschen lokaler Git LFS-Dateien

Mit dem Befehl git lfs prune kannst du Dateien von deinem lokalen Git LFS-Cache löschen:

$ git lfs prune
✔ 4 local objects, 33 retained
Pruning 4 files, (2.1 MB)
✔ Deleted 4 files

Hiermit werden alle lokalen Git LFS-Dateien gelöscht, die als alt angesehen werden. Dies sind alle Dateien, für die keine Referenzen vorhanden sind in:

  • Dem aktuell ausgecheckten Commit
  • Einem Commit, der noch nicht gepusht wurde (zu origin oder entsprechend den Einstellungen von lfs.pruneremotetocheck)
  • Einem aktuellen Commit

In den Standardeinstellungen ist ein aktueller Commit ein Commit, der in den letzten zehn Tagen erstellt wurde. Dies wird errechnet, indem Folgendes addiert wird:

  • Der Wert der Eigenschaft lfs.fetchrecentrefsdays, die wir in Abrufen zusätzlicher Git LFS-Verlaufsinhalte behandelt haben (und die standardmäßig auf sieben gesetzt ist), und
  • der Wert der Eigenschaft lfs.pruneoffsetdays (die standardmäßig auf drei gesetzt ist)
git lfs prune

Du kannst für die Option "prune" ein zeitlich versetztes Löschen konfigurieren, um Git-LFS-Inhalte über einen längeren Zeitraum zu speichern.

# don't prune commits younger than four weeks (7 + 21)
$ git config lfs.pruneoffsetdays 21

Im Gegensatz zur integrierten Speicherbereinigung in Git werden Git-LFS-Inhalte mit "prune" nicht automatisch gelöscht. Daher solltest du git lfs prune regelmäßig nutzen, damit dein lokales Repository nicht zu groß wird.

Du kannst die Auswirkungen eines "prune"-Löschvorgangs mit git lfs prune --dry-run testen:

$ git lfs prune --dry-run
✔ 4 local objects, 33 retained
4 files would be pruned (2.1 MB)

Und mit git lfs prune --verbose --dry-run testest du, welche Git-LFS-Objekte genau mit "prune" gelöscht werden:

$ git lfs prune --dry-run --verbose
✔ 4 local objects, 33 retained
4 files would be pruned (2.1 MB)
* 4a3a36141cdcbe2a17f7bcf1a161d3394cf435ac386d1bff70bd4dad6cd96c48 (2.0 MB)
* 67ad640e562b99219111ed8941cb56a275ef8d43e67a3dac0027b4acd5de4a3e (6.3 KB)
* 6f506528dbf04a97e84d90cc45840f4a8100389f570b67ac206ba802c5cb798f (1.7 MB)
* a1d7f7cdd6dba7307b2bac2bcfa0973244688361a48d2cebe3f3bc30babcf1ab (615.7 KB)

Die im Modus --verbose ausgegebenen Hexadezimal-Strings sind SHA-256-Hashes (auch Objekt-IDs oder OIDs genannt) der mit "prune" zu löschenden Git-LFS-Objekte. Im Abschnitt Pfade oder Commits finden, die auf ein Git-LFS-Objekt verweisen erklären wir dir genauer, wie du mehr über die mit "prune" zu löschenden Objekte erfährst.

Um ganz sicherzugehen, kannst du mit --verify-remote überprüfen, ob deine Git-LFS-Objekte in den Git-LFS-Speicher kopiert worden sind, bevor du diese Objekte mit der Option "prune" löschst:

$ git lfs prune --verify-remote
✔ 16 local objects, 2 retained, 12 verified with remote
Pruning 14 files, (1.7 MB)
✔ Deleted 14 files

Zwar wird das Löschen mit "prune" dadurch verlangsamt, doch du kannst dich darauf verlassen, dass alle so gelöschten Objekt vom Server wiederherstellbar sind. Wenn du die Option --verify-remote für dein System dauerhaft aktivieren willst, kannst du die Eigenschaft lfs.pruneverifyremotealways global konfigurieren:

$ git config --global lfs.pruneverifyremotealways true

Alternativ kannst du die Remote-Überprüfung nur für das Repository in diesem Zusammenhang aktivieren, indem du aus dem Befehl oben die Option --global entfernst.

Löschen von Git LFS-Remote-Dateien vom Server

Mit dem Befehlszeilen-Client von Git LFS können Dateien mit der Option "prune" nicht vom Server gelöscht werden. Das Löschen ist daher vom Hostinganbieter abhängig.

In Bitbucket Cloud kannst du Git-LFS-Dateien über Repository Settings (Repository-Einstellungen) > Git LFS (Git LFS) ansehen und löschen.

Bitbucket Cloud: LFS-Dateien vom Server löschen

Beachte, dass jede Git-LFS-Datei mit einem SHA-256-OID indiziert ist. Die Pfade, die auf die jeweilige Datei verweisen, sind in der Benutzeroberfläche nicht sichtbar. Da mehrere Commits möglich sind, könnte es auch viele verschiedene Pfade geben, die auf ein bestimmtes Objekt verweisen, daher würde es sehr lange dauern, diese Pfade aufzurufen.

Zur Bestimmung des tatsächlichen Inhalts einer Git LFS-Datei hast du drei Optionen:

  • Sieh dir die Dateivoransicht und den Dateityp in der linken Spalte der Git-LFS-UI von Bitbucket an.
  • Lade die Datei herunter, indem du in Bitbucket den Link in der rechten Spalte der Git-LFS-UI-Suche für Commits, die auf den SHA-256-OID des Git-LFS-Objekts verweisen, verwendest. Darauf gehen wir im nächsten Abschnitt genauer ein.

Suche nach Pfaden oder Commits, die ein Git LFS-Objekt referenzieren

Wenn du in Git LFS einen SHA-256-OID hast, kannst du mit git log --all -p -S <OID> bestimmen, welche Commits auf diesen OID verweisen:

$ git log --all -p -S 3b6124b8b01d601fa20b47f5be14e1be3ea7759838c1aac8f36df4859164e4cc
commit 22a98faa153d08804a63a74a729d8846e6525cb0
Author: Tim Pettersen <tpettersen@atlassian.com>
Date: Wed Jul 27 11:03:27 2016 +1000
Projectiles and exploding asteroids
diff --git a/Assets/Sprites/projectiles-spritesheet.png
new file mode 100755
index 0000000..49d7baf
--- /dev/null
+++ b/Assets/Sprites/projectiles-spritesheet.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3b6124b8b01d601fa20b47f5be14e1be3ea7759838c1aac8f36df4859164e4cc
+size 21647

Dieser git log-Befehl generiert einen Patch (-p) von Commits aller Branches (--all), bei denen eine Zeile hinzugefügt oder entfernt wurde (-S), die den angegebenen String enthält (eine Git LFS SHA-256 OID).

Der Patch zeigt Commit und Pfad zum LFS-Objekt an und auch, wer ihn hinzugefügt hat und wann er committet wurde. Wenn du den Commit einfach auscheckst, lädt Git LFS die Datei wenn nötig herunter und legt sie in deiner Arbeitskopie ab.

Wenn du vermutest, dass ein spezielles Git-LFS-Objekt in deinem aktuellen HEAD oder in einem bestimmten Branch ist, kannst du mit git grep den darauf verweisenden Dateipfad ausfindig machen:

# find a particular object by OID in HEAD
$ git grep 3b6124b8b01d601fa20b47f5be14e1be3ea7759838c1aac8f36df4859164e4cc HEAD
HEAD:Assets/Sprites/projectiles-spritesheet.png:oid sha256:3b6124b8b01d601fa20b47f5be14e1be3ea7759838c1aac8f36df4859164e4cc
# find a particular object by OID on the "power-ups" branch
$ git grep e88868213a5dc8533fc9031f558f2c0dc34d6936f380ff4ed12c2685040098d4 power-ups
power-ups:Assets/Sprites/shield2.png:oid sha256:e88868213a5dc8533fc9031f558f2c0dc34d6936f380ff4ed12c2685040098d4

Du kannst HEAD oder power-ups durch einen beliebigen Ref, Commit oder Baum ersetzen, der das Git-LFS-Objekt beinhaltet.

Einbeziehen/Ausschließen von Git LFS-Dateien

Es kann jedoch auch sein, dass du für einen bestimmten Commit nur einen Teil der verfügbaren Git-LFS-Inhalte herunterladen willst. Wenn du z. B. CI-Builds für Unit-Tests konfigurierst, brauchst du nur den Quellcode. Sehr große Dateien, die zur Codeerstellung nicht nötig sind, wirst du dann ausschließen wollen.

Mit git lfs fetch -X (oder --exclude) kannst du ein Muster oder ein Unterverzeichnis ausschließen:

$ git lfs fetch -X "Assets/**"

Andernfalls solltest du nur ein bestimmtes Muster oder ein Unterverzeichnis einschließen. Ein Tontechniker könnte z. B. nur ogg- und wav-Dateien mithilfe von git lfs fetch -I (oder --include) abrufen:

$ git lfs fetch -I "*.ogg,*.wav"

Wenn du include- und exclude-Anweisungen zum Einschließen bzw. Ausschließen kombinierst, werden nur die Dateien abgerufen, die dem include-Muster und zugleich nicht dem exclude-Muster entsprechen. Zum Beispiel kannst du alle Dateien außer GIFs in deinem Assets-Verzeichnis abrufen. Das geht so:

$ git lfs fetch -I "Assets/**" -X "*.gif"

Auf exclude- und include-Anweisungen sind dieselben Muster wie auf git lfs track und .gitignore anwendbar. Diese Muster kannst du mit den Konfigurationseigenschaften lfs.fetchinclude und lfs.fetchexclude für ein bestimmtes Repository als dauerhaft definieren:

$ git config lfs.fetchinclude "Assets/**"
$ git config lfs.fetchexclude "*.gif"

Diese Einstellungen kannst du durch Anhängen der Option --global auch auf jedes andere Repository in deinem System anwenden.

Sperren von Git LFS-Dateien

Leider gibt es für Merge-Konflikte bei Binärdateien keine allgemeine Lösung. Üblicherweise versucht man Merging-Konflikten in Versionskontrollsystemen durch Sperren von Dateien vorzubeugen. Noch unterstützt Git LFS Dateisperrungen nicht. Allerdings haben wir hier einen ausführlichen Vorschlag zum Implementieren von Dateisperrungen. Wir arbeiten bereits an der Implementierung und können mit dem nächsten Release von Git LFS hoffentlich bald eine Lösung anbieten.

Bis dahin ist die Methode zum Vermeiden von Merge-Konflikten die Kommunikation mit den Teamkollegen, bevor du Änderungen an einer Binärdatei vornimmst, die möglicherweise zur gleichen Zeit von jemand anders ebenfalls bearbeitet wird.

Funktionsweise von Git LFS

Wenn du mehr über die Filter "clean" und "smudge", Hooks, die vor dem Pushen ausgeführt werden, sowie andere interessante Git-LFS-Hintergründe erfahren willst, sieh dir diese Präsentation von Atlassian zu Git LFS von der LinuxCon 2016 an: