Verwalten großer Binärdateien mit Git


523

Ich suche nach Meinungen zum Umgang mit großen Binärdateien, von denen mein Quellcode (Webanwendung) abhängig ist. Wir diskutieren derzeit verschiedene Alternativen:

  1. Kopieren Sie die Binärdateien von Hand.
    • Pro: Ich bin mir nicht sicher.
    • Contra: Ich bin stark dagegen, da dies die Wahrscheinlichkeit von Fehlern beim Einrichten einer neuen Site / beim Migrieren der alten Site erhöht. Baut eine weitere Hürde auf.
  2. Verwalten Sie sie alle mit Git .
    • Pro: Entfernt die Möglichkeit, das Kopieren einer wichtigen Datei zu vergessen
    • Contra: Bläht das Repository auf und verringert die Flexibilität bei der Verwaltung der Codebasis. Das Auschecken, Klonen usw. dauert eine Weile.
  3. Separate Repositorys.
    • Pro: Das Auschecken / Klonen des Quellcodes ist wie immer schnell und die Bilder werden ordnungsgemäß in ihrem eigenen Repository archiviert.
    • Contra: Entfernt die Einfachheit, das einzige Git-Repository im Projekt zu haben. Es werden sicherlich einige andere Dinge vorgestellt, über die ich nicht nachgedacht habe.

Was sind deine Erfahrungen / Gedanken dazu?

Außerdem: Hat jemand Erfahrung mit mehreren Git-Repositorys und deren Verwaltung in einem Projekt?

Die Dateien sind Bilder für ein Programm, das PDFs mit diesen Dateien generiert. Die Dateien ändern sich nicht sehr oft (wie in Jahren), sind aber für ein Programm sehr relevant. Das Programm funktioniert nicht ohne die Dateien.


26
Was ist, wenn eine Versionskontrolle der Binärdatei erforderlich ist? Ich denke an Künstlerteams, die an Vermögenswerten arbeiten.
Dan

3
Wenn es notwendig ist, müssen Sie Ihre verfügbaren Ressourcen (Festplatte, Bandbreite, CPU-Zeit) gegen den Vorteil abwägen, den Sie erhalten.
pi.

4
Beachten Sie, dass Git ohne Dateisperrung nicht besonders gut ist, wenn mehrere Personen an derselben Binärdatei arbeiten müssen.
Jojo


Antworten:


177

Wenn das Programm ohne die Dateien nicht funktioniert, scheint es eine schlechte Idee zu sein, sie in ein separates Repo aufzuteilen. Wir haben große Testsuiten, die wir in ein separates Repo aufteilen, aber das sind wirklich "Hilfs" -Dateien.

Möglicherweise können Sie die Dateien jedoch in einem separaten Repo verwalten und dann verwenden git-submodule, um sie auf vernünftige Weise in Ihr Projekt zu ziehen. Sie hätten also immer noch den vollständigen Verlauf Ihrer gesamten Quelle, aber nach meinem Verständnis hätten Sie nur die eine relevante Revision Ihres Bild-Submoduls. Die Funktion git-submodulesoll Ihnen helfen, die richtige Version des Codes mit der richtigen Version der Bilder in Einklang zu bringen.

Hier ist eine gute Einführung in Submodule aus Git Book.


11
"So wie ich es verstehe, hätten Sie nur die eine relevante Revision Ihres Bild-Submoduls." Ich denke nicht, dass das richtig ist.
Robin Green

22
Tatsächlich. Ein Submodul ist ein vollständiges Git-Repository, das zufällig im übergeordneten Repository verschachtelt ist. Es kennt seine gesamte Geschichte. Sie könnten weniger häufig darin festlegen, aber wenn Sie dieselben Dinge darin speichern, die Sie im übergeordneten Element haben würden, treten dieselben Probleme auf, die das übergeordnete Element haben würde.
Cascabel

5
Dies ist eine ziemlich schlechte Lösung, wenn Sie große Binärdateien haben, die sich in regelmäßigen Abständen ändern. Wir haben ein Repository, das schrecklich aufgebläht ist, weil bei jedem Build eine neue Binärdatei darin gespeichert wird. Wenn Sie nicht mit Windows arbeiten, wie unten erwähnt, ist Annex eine gute Lösung. Wenn Sie unter Windows sind ... müssen Sie einfach weiter suchen.
AA Grapsas

4
Ein weiteres Problem bei großen Binärdateien im Repo ist die Leistung. Git wurde nicht für große Binärdateien entwickelt und sobald die Repo-Größe auf 3G + steigt, sinkt die Leistung schnell. Dies bedeutet, dass große Binärdateien im Repo Ihre Hosting-Optionen einschränken.
Zoul

Submodule können die Anforderungen an die Checkout-Datenübertragung reduzieren, wenn Sie das Submodul kreativ missbrauchen: Wenn Sie den Inhalt des Submoduls aktualisieren möchten, erstellen Sie ein neues Commit ohne übergeordnetes Element und zeigen Sie dann das Superprojekt (Haupt-Git-Repo) auf das neu erstellte Commit ohne übergeordnetes Element. Dies erzeugt logischerweise einen getrennten Verlauf für das Submodul, aber im Gegenzug ist jede Version des Submoduls einfacher zu übertragen, da diese Version keinen Verlauf hat.
Mikko Rantalainen

310

Ich habe kürzlich den Git-Anhang entdeckt, den ich großartig finde. Es wurde entwickelt, um große Dateien effizient zu verwalten. Ich benutze es für meine Foto- / Musiksammlungen (usw.). Die Entwicklung des Git-Anhangs ist sehr aktiv. Der Inhalt der Dateien kann aus dem Git-Repository entfernt werden, nur die Baumhierarchie wird von Git verfolgt (über Symlinks). Um jedoch den Inhalt der Datei zu erhalten, ist nach dem Ziehen / Drücken ein zweiter Schritt erforderlich, z.

$ git annex add mybigfile
$ git commit -m'add mybigfile'
$ git push myremote
$ git annex copy --to myremote mybigfile ## This command copies the actual content to myremote
$ git annex drop mybigfile ## Remove content from local repo
...
$ git annex get mybigfile ## Retrieve the content
## or to specify the remote from which to get:
$ git annex copy --from myremote mybigfile

Es stehen viele Befehle zur Verfügung und es gibt eine großartige Dokumentation auf der Website. Ein Paket ist auf Debian verfügbar .


11
Whoa! Upvote für Großartigkeit! Dies setzt eine Idee um, die ich kürzlich hatte, und vieles mehr. Es ist nicht weniger in Haskell geschrieben. Git-Media ist übrigens eine gute Alternative.
cdunn2001

33
Annex unterstützt Windows jedoch nicht. Was für Spieleentwickler problematisch ist.
AA Grapsas

7
Ich habe gehört, Steam stellt die Unterstützung für Windows ein und fügt Unterstützung für Linux hinzu ...;) Ernsthaft, wie schwer kann es sein, dies zu portieren? Ich denke, ein durchschnittlicher Spieleentwickler könnte das tun.
Sam Watkins

4
@EstebanBrenes Der eigentliche Deal-Breaker ist, dass Windows-Symlinks in der normalen Konfiguration erhöhte Berechtigungen zum Erstellen erfordern.
Laurens Holst

4
Ich habe gerade diese Seite gefunden . Es heißt, dass jetzt git annexauch unter Windows verfügbar ist . Wenn jemand es jemals in Windows getestet hat, würde ich gerne etwas über seine Erfahrungen erfahren!
Kouichi C. Nakamura

49

Eine weitere Lösung ist seit April 2015 Git Large File Storage (LFS) (von GitHub).

Es verwendet git-lfs (siehe git-lfs.github.com ) und wird mit einem Server getestet, der dies unterstützt: lfs-test-server :
Sie können Metadaten nur im Git-Repo und in der großen Datei an anderer Stelle speichern.

https://cloud.githubusercontent.com/assets/1319791/7051226/c4570828-ddf4-11e4-87eb-8fc165e5ece4.gif


3
lfs-test-serverwird als nicht für die Produktion bestimmt erklärt. Eigentlich arbeite ich am Produktions-LFS-Server ( github.com/artemkin/git-lfs-server ). Es ist in Bearbeitung, aber bereits wartbar, und wir testen es intern.
Stas

Können Sie frühere Versionen einer solchen Binärdatei mit git lfs auschecken?
Mucaho

1
@mucaho Sie sollten: Die Syntax von git checkout bleibt unverändert und das lfs-Smudge-Skript sollte weiterhin aufgerufen werden.
VonC

31

Schauen Sie sich git bup an , eine Git-Erweiterung zum intelligenten Speichern großer Binärdateien in einem Git-Repository.

Sie möchten es als Submodul haben, müssen sich aber keine Sorgen machen, dass das Repository schwer zu handhaben ist. Einer ihrer Anwendungsbeispiele ist das Speichern von VM-Images in Git.

Ich habe eigentlich keine besseren Komprimierungsraten gesehen, aber meine Repositorys enthalten keine wirklich großen Binärdateien.

Ihr Kilometerstand kann variieren.


3
bup bietet Speicherplatz (intern mithilfe von Paritätsarchiven für Redundanz und git für Komprimierung, Dedup und Verlauf), erweitert git jedoch nicht. git-annex ist eine Git-Erweiterung, die ein Bup-Speicher-Backend bereitstellt .
Tobu

@Tobu Als ich dies gepostet habe, gab es noch keinen Git-Anhang (in Mainstream-Versionen)
siehe

2
bup ist definitiv interessant für die Verwaltung großer Dateien. Ich wollte auf einen Unterschied in der Benutzeroberfläche hinweisen: Sie verwenden Bup-Befehle außerhalb eines Repository-Kontexts, und Git ist ein Implementierungsdetail.
Tobu

27

Sie können auch Git-Fett verwenden . Ich mag, dass es nur auf Lager Python und hängt rsync. Es unterstützt auch den üblichen Git-Workflow mit den folgenden selbsterklärenden Befehlen:

git fat init
git fat push
git fat pull

Darüber hinaus müssen Sie eine Gitfat-Datei in Ihr Repository einchecken und Ihre Gitattributes ändern, um die Dateierweiterungen anzugeben, die Sie verwalten möchten git fat.

Sie fügen eine Binärdatei mit der Normalen hinzu git add, die wiederum git fatbasierend auf Ihren Gitattributes-Regeln aufgerufen wird.

Schließlich hat es den Vorteil, dass der Speicherort Ihrer Binärdateien von Repositorys und Benutzern gemeinsam genutzt werden kann und alles unterstützt rsync tut.

UPDATE: Verwenden Sie kein Git-Fat, wenn Sie eine Git-SVN-Bridge verwenden. Am Ende werden die Binärdateien aus Ihrem Subversion-Repository entfernt. Wenn Sie jedoch ein reines Git-Repository verwenden, funktioniert es hervorragend.


26

Ich würde Submodule (als Pat Notz) oder zwei verschiedene Repositories verwenden. Wenn Sie Ihre Binärdateien zu oft ändern, würde ich versuchen, die Auswirkungen des riesigen Repositorys zu minimieren, das den Verlauf bereinigt:

Ich hatte vor einigen Monaten ein sehr ähnliches Problem: ~ 21 GB MP3-Dateien, nicht klassifiziert (schlechte Namen, schlechte ID3s, weiß nicht, ob mir diese MP3-Datei gefällt oder nicht ...) und auf drei Computern repliziert.

Ich habe ein externes Festplattenlaufwerk mit dem Haupt-Git-Repository verwendet und es in jeden Computer geklont. Dann fing ich an, sie auf die gewohnte Weise zu klassifizieren (drücken, ziehen, zusammenführen ... viele Male löschen und umbenennen).

Am Ende hatte ich nur ~ 6 GB MP3-Dateien und ~ 83 GB im .git-Verzeichnis. Ich habe git-write-treeund benutztgit-commit-tree eine neue zu begehen, zu schaffen , ohne Vorfahren zu begehen, und begann zu , dass eine neue Niederlassung Zeige begehen. Das "Git-Protokoll" für diesen Zweig zeigte nur ein Commit.

Dann habe ich den alten Zweig gelöscht, nur den neuen Zweig beibehalten, die Ref-Protokolle gelöscht und "git prune" ausgeführt: Danach haben meine .git-Ordner nur noch ~ 6 GB gewichtet ...

Sie können das riesige Repository von Zeit zu Zeit auf die gleiche Weise "bereinigen": Ihre "Git-Klone" werden schneller sein.


Ich habe einmal etwas Ähnliches gemacht, bei dem ich ein Repository aufteilen musste, das ich versehentlich in zwei verschiedene zusammengeführt habe. Interessantes Nutzungsmuster. :)
pi.

1
Wäre das dasselbe wie nur: rm -f .git; git init; git hinzufügen. ;; git commit -m "Verwende die Geschichte."
Pat Notz

1
Ja, das ist nur in meinem MP3-Fall dasselbe. Aber manchmal möchten Sie Ihre Zweige und Tags nicht berühren (keine Speicherplatzreduzierung in öffentlichen Repositorys), sondern nur ein "Git-Klonen / Abrufen / Ziehen" nur eines Zweigs beschleunigen (weniger Platz für dedizierte Zweige). Zweigstellen-Repositories).
Daniel Fanjul

13

Die Lösung, die ich vorschlagen möchte, basiert auf verwaisten Zweigen und einem leichten Missbrauch des Tag-Mechanismus, der im Folgenden als * Orphan Tags Binary Storage (OTABS) bezeichnet wird.

TL; DR 12-01-2017 Wenn Sie Githubs LFS oder einen anderen Drittanbieter verwenden können, sollten Sie dies auf jeden Fall tun. Wenn Sie nicht können, dann lesen Sie weiter. Seien Sie gewarnt, diese Lösung ist ein Hack und sollte als solche behandelt werden.

Wünschenswerte Eigenschaften von OTABS

  • es ist ein reines git und git nur Lösung - es erledigt die Arbeit ohne Software von Drittanbietern (wie git-annex) oder Infrastruktur von Drittanbietern (wie Githubs LFS).
  • Die Binärdateien werden effizient gespeichert , dh der Verlauf Ihres Repositorys wird nicht aufgebläht.
  • git pullund git fetcheinschließlich git fetch --allsind immer noch bandbreiteneffizient , dh nicht alle großen Binärdateien werden standardmäßig von der Fernbedienung abgerufen.
  • es funktioniert unter Windows .
  • Es speichert alles in einem einzigen Git-Repository .
  • Es ermöglicht das Löschen veralteter Binärdateien (im Gegensatz zu bup).

Unerwünschte Eigenschaften von OTABS

  • Dies macht git clonemöglicherweise ineffizient (aber nicht unbedingt, abhängig von Ihrer Verwendung). Wenn Sie diese Lösung bereitstellen, müssen Sie möglicherweise Ihren Kollegen raten, sie git clone -b master --single-branch <url>anstelle von zu verwenden git clone. Dies liegt daran, dass git clone standardmäßig buchstäblich das gesamte Repository klont, einschließlich Dinge, für die Sie normalerweise Ihre Bandbreite nicht verschwenden möchten, wie nicht referenzierte Commits. Entnommen aus SO 4811434 .
  • Dies macht die git fetch <remote> --tagsBandbreite ineffizient, aber nicht unbedingt den Speicher ineffizient. Sie können Ihren Kollegen jederzeit raten, es nicht zu verwenden.
  • Sie müssen regelmäßig einen git gcTrick anwenden, um Ihr Repository von allen Dateien zu bereinigen, die Sie nicht mehr benötigen.
  • es ist nicht so effizient wie bup oder git-bigfiles . Aber es ist jeweils besser für das geeignet, was Sie versuchen, und mehr von der Stange. Es ist wahrscheinlich, dass Sie Probleme mit Hunderttausenden kleiner Dateien oder mit Dateien im Bereich von Gigabyte haben, aber lesen Sie weiter, um dieses Problem zu umgehen.

Hinzufügen der Binärdateien

Bevor Sie beginnen, stellen Sie sicher, dass Sie alle Ihre Änderungen festgeschrieben haben, Ihr Arbeitsbaum auf dem neuesten Stand ist und Ihr Index keine nicht festgeschriebenen Änderungen enthält. Es kann eine gute Idee sein, alle Ihre lokalen Niederlassungen auf Ihre Fernbedienung (Github usw.) zu übertragen, falls eine Katastrophe eintreten sollte.

  1. Erstellen Sie einen neuen verwaisten Zweig. git checkout --orphan binaryStuffwird den Trick machen. Dies erzeugt einen Zweig, der vollständig von jedem anderen Zweig getrennt ist, und das erste Commit, das Sie in diesem Zweig vornehmen, hat kein übergeordnetes Element, wodurch es zu einem Root-Commit wird.
  2. Bereinigen Sie Ihren Index mit git rm --cached * .gitignore.
  3. Atmen Sie tief ein und löschen Sie den gesamten Arbeitsbaum mit rm -fr * .gitignore. Das interne .gitVerzeichnis bleibt unberührt, da der *Platzhalter nicht mit ihm übereinstimmt.
  4. Kopieren Sie in Ihre VeryBigBinary.exe oder Ihr VeryHeavyDirectory /.
  5. Fügen Sie es hinzu und legen Sie es fest.
  6. Jetzt wird es schwierig - wenn Sie es als Zweig in die Fernbedienung schieben, laden alle Ihre Entwickler es herunter, wenn sie das nächste Mal git fetchihre Verbindung verstopfen. Sie können dies vermeiden, indem Sie ein Tag anstelle eines Zweigs verschieben. Dies kann sich weiterhin auf die Bandbreite und den Dateisystemspeicher Ihres Kollegen auswirken, wenn dieser die Gewohnheit hat zu tippen git fetch <remote> --tags, aber zur Problemumgehung weiterlesen. Fahre fort undgit tag 1.0.0bin
  7. Schieben Sie Ihr Waisen-Tag git push <remote> 1.0.0bin.
  8. Damit Sie Ihren Binärzweig niemals versehentlich verschieben, können Sie ihn löschen git branch -D binaryStuff. Ihr Commit wird nicht für die Speicherbereinigung markiert, da ein darauf verwaltetes verwaistes Tag 1.0.0binausreicht, um es am Leben zu erhalten.

Auschecken der Binärdatei

  1. Wie kann ich (oder meine Kollegen) die Datei VeryBigBinary.exe in den aktuellen Arbeitsbaum auschecken lassen? Wenn Ihr aktueller Arbeitszweig zum Beispiel Master ist, können Sie dies einfach tun git checkout 1.0.0bin -- VeryBigBinary.exe.
  2. Dies schlägt fehl, wenn Sie das Orphan-Tag nicht 1.0.0binheruntergeladen haben. In diesem Fall müssen Sie dies git fetch <remote> 1.0.0binvorher tun .
  3. Sie können die VeryBigBinary.exein die Ihres Masters einfügen .gitignore, so dass niemand in Ihrem Team versehentlich die Hauptgeschichte des Projekts mit der Binärdatei verschmutzt.

Vollständiges Löschen der Binärdatei

Wenn Sie VeryBigBinary.exe vollständig aus Ihrem lokalen Repository, Ihrem Remote-Repository und den Repositorys Ihres Kollegen löschen möchten, können Sie einfach:

  1. Löschen Sie das verwaiste Tag auf der Fernbedienung git push <remote> :refs/tags/1.0.0bin
  2. Löschen Sie das verwaiste Tag lokal (löscht alle anderen nicht referenzierten Tags) git tag -l | xargs git tag -d && git fetch --tags. Entnommen aus SO 1841341 mit geringfügiger Modifikation.
  3. Verwenden Sie einen git gc-Trick, um Ihr jetzt nicht referenziertes Commit lokal zu löschen. git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc "$@". Außerdem werden alle anderen nicht referenzierten Commits gelöscht. Entnommen aus SO 1904860
  4. Wenn möglich, wiederholen Sie den Trick git gc auf der Fernbedienung. Dies ist möglich, wenn Sie Ihr Repository selbst hosten und dies bei einigen Git-Anbietern wie Github oder in bestimmten Unternehmensumgebungen möglicherweise nicht möglich ist. Wenn Sie bei einem Anbieter hosten, der Ihnen keinen SSH-Zugriff auf die Fernbedienung gewährt, lassen Sie es einfach sein. Es ist möglich, dass die Infrastruktur Ihres Providers Ihr nicht referenziertes Commit in seiner eigenen süßen Zeit bereinigt. Wenn Sie sich in einer Unternehmensumgebung befinden, können Sie Ihrer IT raten, etwa einmal pro Woche einen Cron-Job-Müll auszuführen, der Ihre Fernbedienung sammelt. Ob sie dies tun oder nicht, hat keinen Einfluss auf Ihr Team in Bezug auf Bandbreite und Speicherplatz, solange Sie Ihren Kollegen raten, immer git clone -b master --single-branch <url>statt git clone.
  5. Alle Ihre Kollegen, die veraltete Orphan-Tags entfernen möchten, müssen nur die Schritte 2-3 anwenden.
  6. Anschließend können Sie die Schritte 1 bis 8 unter Hinzufügen der Binärdateien wiederholen , um ein neues verwaistes Tag zu erstellen 2.0.0bin. Wenn Sie sich Sorgen machen, dass Ihre Kollegen tippen git fetch <remote> --tags, können Sie es tatsächlich erneut benennen 1.0.0bin. Dadurch wird sichergestellt, dass beim nächsten Abrufen aller Tags die alten 1.0.0binnicht referenziert und für die nachfolgende Speicherbereinigung markiert werden (mithilfe von Schritt 3). Wenn Sie versuchen, ein Tag auf der Fernbedienung zu überschreiben, müssen Sie Folgendes verwenden -f:git push -f <remote> <tagname>

Nachwort

  • OTABS berührt weder Ihren Master noch andere Quellcode- / Entwicklungszweige. Die Commit-Hashes, die gesamte Historie und die geringe Größe dieser Zweige bleiben davon unberührt. Wenn Sie Ihren Quellcode-Verlauf bereits mit Binärdateien aufgebläht haben, müssen Sie ihn als separate Arbeit bereinigen. Dieses Skript könnte nützlich sein.

  • Bestätigt, um mit git-bash unter Windows zu arbeiten.

  • Es ist eine gute Idee, eine Reihe von Standard-Trics anzuwenden , um die Speicherung von Binärdateien effizienter zu gestalten. Durch häufiges Ausführen von git gc(ohne zusätzliche Argumente) optimiert git die zugrunde liegende Speicherung Ihrer Dateien mithilfe von Binärdeltas. Wenn es jedoch unwahrscheinlich ist, dass Ihre Dateien von Commit zu Commit ähnlich bleiben, können Sie binäre Deltas vollständig ausschalten. Da es keinen Sinn macht, bereits komprimierte oder verschlüsselte Dateien wie .zip, .jpg oder .crypt zu komprimieren, können Sie mit git die Komprimierung des zugrunde liegenden Speichers deaktivieren. Leider ist dies eine Alles-oder-Nichts-Einstellung, die sich auch auf Ihren Quellcode auswirkt.

  • Möglicherweise möchten Sie Teile von OTABS skripten, um eine schnellere Verwendung zu ermöglichen. Insbesondere das Skripting der Schritte 2-3 vom vollständigen Löschen von Binärdateien in einen updateGit-Hook kann dem Git-Abruf eine überzeugende, aber möglicherweise gefährliche Semantik verleihen ("Abrufen und Löschen aller veralteten Dateien ").

  • Möglicherweise möchten Sie Schritt 4 des vollständigen Löschens von Binärdateien überspringen , um einen vollständigen Verlauf aller Binäränderungen auf der Fernbedienung auf Kosten des Aufblähens des zentralen Repositorys zu erhalten. Lokale Repositories bleiben im Laufe der Zeit schlank.

  • In der Java-Welt ist es möglich, diese Lösung mit zu kombinieren maven --offline, um einen reproduzierbaren Offline-Build zu erstellen, der vollständig in Ihrer Versionskontrolle gespeichert ist (mit maven ist dies einfacher als mit gradle). In der Golang-Welt ist es möglich, auf dieser Lösung aufzubauen, um stattdessen Ihren GOPATH zu verwalten go get. In der Python-Welt ist es möglich, dies mit virtualenv zu kombinieren, um eine eigenständige Entwicklungsumgebung zu erstellen, ohne sich bei jedem Build von Grund auf auf PyPi-Server verlassen zu müssen.

  • Wenn Ihre Binär - Dateien sehr oft ändern, wie Build - Artefakte, könnte es eine gute Idee , um Skript eine Lösung , die speichert 5 neueste Versionen der Artefakte in den Orphan - Tags sein monday_bin, tuesday_bin..., friday_binund auch eine Waise Tag für jede Veröffentlichung 1.7.8bin 2.0.0binusw. Sie können die weekday_binalten Binärdateien täglich drehen und löschen. Auf diese Weise erhalten Sie das Beste aus zwei Welten: Sie behalten den gesamten Verlauf Ihres Quellcodes, aber nur den relevanten Verlauf Ihrer binären Abhängigkeiten. Es ist auch sehr einfach, die Binärdateien für ein bestimmtes Tag abzurufen, ohne den gesamten Quellcode mit seinem gesamten Verlauf abzurufen: git init && git remote add <name> <url> && git fetch <name> <tag>sollte dies für Sie tun.


"Sie müssen regelmäßig verwenden git gc" - hörte genau dort auf zu lesen. Warum sollte jemand seinen letzten Sicherheitsgurt zugunsten eines Hacks aufgeben?
user1643723

@ user1643723 git gcist nicht unsicher auszuführen. Alle Ihre baumelnden Commits werden standardmäßig mindestens 30 Tage lang sicher auf der Festplatte gespeichert
Adam Kurkiewicz

Vielen Dank für die ausführliche Beschreibung. Ich wollte dies versuchen, um einige binäre Abhängigkeiten in meinem GitHub-Repo so zu speichern, dass sie nicht standardmäßig heruntergeladen werden, wenn jemand das Repo klont, sondern manuell heruntergeladen und das lokale Repo aktualisiert werden kann. Bei diesem Schritt ist jedoch ein Fehler aufgetreten: git push <remote> 1.0.0bin- remote: error: GH001: Large files detected. You may want to try Git Large File Storage. Es sieht so aus, als würde GitHub dies nicht mehr unterstützen? Die fragliche Binärdatei hatte eine Größe von 100 MB.
user5359531

1
Um ganz ehrlich zu sein, was hält Sie davon ab, LFS zu verwenden, wenn Sie Github für Ihre Arbeit verwenden dürfen? Die Jungs von github haben hart gearbeitet, um dieses Produkt zu entwickeln, und sie hosten es sogar für Sie und ihre Infrastruktur ist darauf optimiert, es zu verwenden. Dieser Hack ist für Situationen gedacht, in denen Sie LFS oder andere Drittanbieter wirklich nicht verwenden können und nach einer reinen Git-Lösung suchen.
Adam Kurkiewicz

Ich habe auch die Antwort aktualisiert, um klarer zu machen, wie hacky diese Lösung tatsächlich ist.
Adam Kurkiewicz

13

Meiner Meinung nach sollten Sie ernsthaft in Betracht ziehen, ein anderes Git-Repository zu verwenden (oder eine andere Möglichkeit, auf diese Dateien zuzugreifen) , wenn Sie diese großen Dateien wahrscheinlich häufig ändern oder wenn Sie beabsichtigen, viele git cloneoder git checkoutzu erstellen.

Wenn Sie jedoch wie wir arbeiten und Ihre Binärdateien nicht häufig geändert werden, ist der erste Klon / Checkout lang, aber danach sollte er so schnell sein, wie Sie möchten (da Ihre Benutzer weiterhin das erste geklonte Repository verwenden, das sie verwenden hätten).


13
Und separate Repos verkürzen die Checkout-Zeit nicht, da Sie immer noch beide Repos auschecken müssen!
Emil Sit

@EmilSit separates Repo könnte die Kaufabwicklung erheblich verkürzen, wenn Sie den Verlauf des "binären Repos" kontinuierlich bereinigen. Darüber hinaus wären Entwickler nicht gezwungen, jedes Mal beide Repos auszuchecken .
FabienAndre

Lassen Sie die Build-Dateien des Hauptmoduls nicht einfach die Binärdateien aus dem zweiten Repo abrufen und einzeln extrahieren (wie hier: stackoverflow.com/questions/1125476/… ).
Akauppi

1
Selbst wenn Ihre Binärdateien nicht häufig geändert werden, können große Dateien Ihren Workflow dennoch beenden, wenn Sie häufig Zweige für die Zusammenarbeit in das Repository verschieben.
Timo Reimann

9

SVN scheint mit binären Deltas effizienter umzugehen als Git.

Ich musste mich für ein Versionsverwaltungssystem für die Dokumentation entscheiden (JPEG-Dateien, PDF-Dateien und ODT-Dateien). Ich habe gerade getestet, wie man eine JPEG-Datei hinzufügt und viermal um 90 Grad dreht (um die Wirksamkeit von binären Deltas zu überprüfen). Das Repository von Git wuchs um 400%. Das Repository von SVN wuchs nur um 11%.

Es sieht also so aus, als ob SVN mit Binärdateien viel effizienter ist.

Meine Wahl ist also Git für Quellcode und SVN für Binärdateien wie Dokumentation.


33
Sie mussten nur "git gc" (Umpacken und Speicherbereinigung) ausführen, nachdem Sie diese 4 Dateien hinzugefügt hatten. Git komprimiert nicht sofort den gesamten hinzugefügten Inhalt, so dass Sie eine Dateigruppenkomprimierung haben (die in Bezug auf die Größe effizienter ist) und nicht die Verzögerung, jedes einzelne hinzugefügte Objekt separat zu komprimieren. Aber auch ohne "git gc" hätte git die Komprimierung ohnehin irgendwann für Sie durchgeführt (nachdem festgestellt wurde, dass sich genügend entpackte Objekte angesammelt haben).
Nachtigall

24
@jpierson Ich habe ein leeres Git-Repository erstellt und ein vollständig weißes BMP-Image mit einer Größe von 41 MB hinzugefügt (und festgeschrieben). Dies führte zu einem Gesamt-Git-Repository mit einer Größe von 328 KB. Nach a wurde git gcdie Gesamtgröße des Git-Repositorys auf 184 KB reduziert. Dann habe ich ein einzelnes Pixel von Weiß in Schwarz geändert und diese Änderung vorgenommen. git gcDie Gesamtgröße des Git-Repositorys wurde auf 388 KB erhöht, und nachdem die Größe des gesamten Git-Repositorys auf 184 KB reduziert wurde. Dies zeigt, dass Git ziemlich gut darin ist, Deltas von Binärdateien zu komprimieren und zu finden.
Tader

6
@jpierson Eine Nebenbemerkung: Ich habe gerade die binären Deltas kommentiert. Git wird Ihren gesamten Speicher verbrauchen und austauschen, wenn es Repositorys mit großen Dateien (GB) verwaltet. Verwenden Sie dazu den Git-Anhang (bereits in einer anderen Antwort erwähnt) ...
Tader

12
@ JanDvorak - niemand hat es erwähnt, weil es völlig falsch ist. Subversion-Kopien sind billig - svnbook.red-bean.com/de/1.7/svn.branchmerge.using.html - ungefähr in der Mitte der Seite.
Joris Timmermans

12
@Tader: Dein Test ist schlecht. Was Sie eine Binärdatei nennen, ähnelt in der Tat (aus der Sicht von git) eher einer Textdatei - der Bitstrom ist byteorientiert, und es müssen sinnvolle, lokalisierte Unterschiede vorgenommen werden. Das Ändern eines Pixels entspricht im Grunde dem Ändern eines Zeichens in einer Textdatei (und wer verwendet heutzutage unkomprimierte Bitmaps?). Versuchen Sie dasselbe Experiment mit einem kleinen Video, einem komprimierten Bild, einer virtuellen Maschine, einer Zip-Datei oder was auch immer - und Sie werden feststellen dieser Git geht nicht effizient mit dem Delta um; In der Tat ist es mit inkompressiblen Daten grundsätzlich unmöglich.
Eamon Nerbonne

4

git clone --filter ab Git 2.19 + flache Klone

Diese neue Option könnte schließlich die endgültige Lösung für das Problem mit Binärdateien sein, wenn die Entwickler von Git und GitHub sie benutzerfreundlich genug machen (was sie beispielsweise für Submodule wohl noch nicht erreicht haben ).

Es ermöglicht tatsächlich nur das Abrufen von Dateien und Verzeichnissen, die Sie für den Server benötigen, und wurde zusammen mit einer Remote-Protokollerweiterung eingeführt.

Damit könnten wir zuerst einen flachen Klon erstellen und dann automatisieren, welche Blobs mit dem Build-System für jeden Build-Typ abgerufen werden sollen.

Es gibt sogar bereits eine --filter=blob:limit<size>, mit der die maximale abzurufende Blob-Größe begrenzt werden kann.

Ich habe ein minimal detailliertes Beispiel dafür bereitgestellt, wie die Funktion aussieht: Wie klone ich nur ein Unterverzeichnis eines Git-Repositorys?


2

Ich suche nach Meinungen zum Umgang mit großen Binärdateien, von denen mein Quellcode (Webanwendung) abhängig ist. Was sind deine Erfahrungen / Gedanken dazu?

Ich persönlich habe bei einigen meiner Cloud-Hosts Synchronisationsfehler mit Git festgestellt, nachdem die Binärdaten meiner Webanwendungen über der 3-GB-Marke lagen . Ich habe damals über BFT Repo Cleaner nachgedacht , aber es fühlte sich wie ein Hack an. Seitdem habe ich begonnen, Dateien nur außerhalb des Git-Bereichs zu halten und stattdessen speziell entwickelte Tools wie Amazon S3 für die Verwaltung, Versionierung und Sicherung von Dateien zu nutzen.

Hat jemand Erfahrung mit mehreren Git-Repositorys und deren Verwaltung in einem Projekt?

Ja. Hugo-Themen werden hauptsächlich auf diese Weise verwaltet. Es ist ein bisschen dick, aber es erledigt den Job.


Mein Vorschlag ist , das richtige Werkzeug für den Job auszuwählen . Wenn es sich um ein Unternehmen handelt und Sie Ihre Codeline auf GitHub verwalten, zahlen Sie das Geld und verwenden Sie Git-LFS. Andernfalls könnten Sie kreativere Optionen wie die dezentrale, verschlüsselte Dateispeicherung mithilfe der Blockchain untersuchen .

Weitere zu berücksichtigende Optionen sind Minio und s3cmd .


0

Schauen Sie sich camlistore an . Es ist nicht wirklich Git-basiert, aber ich finde es besser geeignet für das, was Sie tun müssen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.