Ich suche Meinungen zum Umgang mit großen Binärdateien, von denen mein Quellcode (Webanwendung) abhängig ist. Wir diskutieren derzeit mehrere Alternativen:
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 erzeugt. Die Dateien ändern sich nicht sehr oft (wie in Jahren), sind jedoch für ein Programm sehr relevant. Das Programm wird ohne die Dateien nicht funktionieren.
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 "Hilfsdateien".
Möglicherweise können Sie die Dateien jedoch in einem separaten Repository verwalten und dann 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 Bildersubmoduls. Das git-submodule
Die Funktion soll Ihnen helfen, die korrekte Version des Codes mit der korrekten Version der Bilder in Einklang zu bringen.
Hier ist eine gute Einführung in Submodule von Git Book.
Ich habe git-annex kürzlich entdeckt, was ich großartig finde. Es wurde für die effiziente Verwaltung großer Dateien entwickelt. Ich benutze es für meine Foto/Musik (etc.) Sammlungen. Die Entwicklung von Git-Annex 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 gibt viele Befehle und eine großartige Dokumentation auf der Website. Ein Paket ist verfügbar unter Debian .
Eine andere Lösung ist seit April 2015 Git Large File Storage (LFS) (von GitHub).
Es verwendet git-lfs (siehe git-lfs.github .com) und mit einem Server getestet, der es unterstützt: lfs-test-server :
Sie können Metadaten nur im Git-Repo und die große Datei an anderer Stelle speichern.
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 darüber 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.
Sie können auch git-fat verwenden. Ich mag, dass es nur auf Lager ankommt Python und rsync
. Es unterstützt auch den üblichen Git-Workflow mit den folgenden selbsterklärenden Befehlen:
git fat init
git fat Push
git fat pull
Außerdem 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 dem normalen git add
Hinzu, der wiederum git fat
Auf der Grundlage Ihrer Gitattributes-Regeln aufruft.
Schließlich hat es den Vorteil, dass der Speicherort, an dem Ihre Binärdateien tatsächlich gespeichert sind, für Repositorys und Benutzer freigegeben werden kann und alles unterstützt, was 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 einwandfrei.
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 der Bereinigung des Verlaufs durch das riesige Repository zu minimieren:
Ich hatte vor einigen Monaten ein sehr ähnliches Problem: ~ 21 GB MP3-Dateien, nicht klassifiziert (falsche Namen, falsche ID3s, weiß nicht, ob ich diese MP3-Datei mag 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 wie gewöhnlich zu klassifizieren (mehrmals drücken, ziehen, zusammenführen ... löschen und umbenennen).
Am Ende hatte ich nur ~ 6 GB MP3-Dateien und ~ 83 GB im .git-Verzeichnis. Ich benutzte git-write-tree
und git-commit-tree
, um ein neues Commit ohne Commit-Vorfahren zu erstellen, und startete einen neuen Zweig, der auf dieses Commit verweist. 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-Logs gelöscht und "git Prune" ausgeführt: Danach waren meine .git-Ordner nur noch ~ 6 GB schwer ...
Sie können das riesige Repository von Zeit zu Zeit auf die gleiche Weise "bereinigen": Ihre "Git-Klone" werden schneller sein.
Meiner Meinung nach, wenn Sie wahrscheinlich häufig diese großen Dateien ändern oder wenn Sie vorhaben, eine Menge von git clone
oder git checkout
, dann sollten Sie ernsthaft in Betracht ziehen, ein anderes Git-Repository (oder eine andere Möglichkeit, auf diese Dateien zuzugreifen) zu verwenden.
Wenn Sie jedoch wie wir arbeiten und Ihre Binärdateien nicht häufig geändert werden, dauert das erste Klonen/Auschecken lange, danach sollte es jedoch so schnell sein, wie Sie möchten (wenn Ihre Benutzer weiterhin das erste geklonte Repository verwenden, das sie verwenden) hätten).
Die Lösung, die ich vorschlagen möchte, basiert auf Orphan-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 unbedingt 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
git pull
Und git fetch
, Einschließlich git fetch --all
, Sind immer noch bandbreiteneffizient , dh nicht alle großen Binärdateien sind bandbreiteneffizient Standardmäßig von der Fernbedienung abgerufen.Unerwünschte Eigenschaften von OTABS
git clone
möglicherweise ineffizient (aber nicht unbedingt, abhängig von Ihrer Verwendung). Wenn Sie diese Lösung bereitstellen, müssen Sie möglicherweise Ihren Kollegen raten, git clone -b master --single-branch <url>
Anstelle von git clone
Zu verwenden. Dies liegt daran, dass git clone standardmäßig das gesamte Repository klont , einschließlich Dingen, für die Sie normalerweise keine Bandbreite verschwenden möchten, wie z. B. nicht referenzierte Commits. Entnommen aus SO 4811434 .git fetch <remote> --tags
ineffizient, aber nicht unbedingt die Speicherung ineffizient. Sie können Ihren Kollegen jederzeit raten, es nicht zu verwenden.git gc
- Trick anwenden, um Ihr Repository von allen Dateien zu säubern, die Sie nicht mehr benötigen.Hinzufügen der Binärdateien
Bevor Sie beginnen, stellen Sie sicher, dass Sie alle Änderungen festgeschrieben haben, dass Ihr Arbeitsbaum auf dem neuesten Stand ist und Ihr Index keine nicht festgeschriebenen Änderungen enthält. Es könnte eine gute Idee sein, alle Ihre lokalen Niederlassungen auf Ihre Fernbedienung (Github usw.) zu übertragen, falls eine Katastrophe eintreten sollte.
git checkout --Orphan binaryStuff
Erledigt den Trick. Dadurch wird ein Zweig erstellt, der von keinem anderen Zweig vollständig getrennt ist, und der erste Festschreibungsvorgang, den Sie in diesem Zweig ausführen, hat keinen übergeordneten Zweig. Dies macht ihn zu einem Root-Festschreibungsvorgang.git rm --cached * .gitignore
.rm -fr * .gitignore
. Das interne .git
- Verzeichnis bleibt unberührt, da der Platzhalter *
Nicht damit übereinstimmt.git fetch
Aufrufen, um ihre Verbindung zu blockieren. Sie können dies vermeiden, indem Sie ein Tag anstelle einer Verzweigung drücken. Dies kann sich immer noch auf die Bandbreite und den Dateisystemspeicher Ihres Kollegen auswirken, wenn er die Angewohnheit hat, git fetch <remote> --tags
Einzugeben. Lesen Sie jedoch weiter, um dieses Problem zu umgehen. Mach weiter und git tag 1.0.0bin
git Push <remote> 1.0.0bin
.git branch -D binaryStuff
. Ihr Commit wird nicht für die Garbage Collection markiert, da ein darauf verweisendes Orphan-Tag 1.0.0bin
Ausreicht, um es am Leben zu erhalten.Auschecken der Binärdatei
git checkout 1.0.0bin -- VeryBigBinary.exe
.1.0.0bin
Nicht heruntergeladen haben. In diesem Fall müssen Sie vorher git fetch <remote> 1.0.0bin
.VeryBigBinary.exe
In den .gitignore
Ihres Masters einfügen, damit 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 Ihrer Kollegen löschen möchten, haben Sie folgende Möglichkeiten:
git Push <remote> :refs/tags/1.0.0bin
git tag -l | xargs git tag -d && git fetch --tags
. Entnommen aus SO 1841341 mit geringfügiger Änderung.git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc "[email protected]"
. Es werden auch alle anderen nicht referenzierten Commits gelöscht. Entnommen aus SO 190486git clone -b master --single-branch <url>
Anstelle von git clone
Zu verwenden.2.0.0bin
Zu erstellen. Wenn Sie besorgt sind, dass Ihre Kollegen git fetch <remote> --tags
Eingeben, können Sie den Namen erneut eingeben 1.0.0bin
. Dadurch wird sichergestellt, dass beim nächsten Abrufen aller Tags das alte 1.0.0bin
Nicht referenziert und für die nachfolgende Garbage Collection markiert wird (mithilfe von Schritt 3). Wenn Sie versuchen, ein Tag auf der Fernbedienung zu überschreiben, müssen Sie -f
Wie folgt verwenden: git Push -f <remote> <tagname>
Nachwort
OTABS berührt weder Ihren Master noch andere Quellcode- oder Entwicklungszweige. Die Commit-Hashes, der gesamte Verlauf und die geringe Größe dieser Zweige sind nicht betroffen. 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 unter Windows mit Git-Bash zu arbeiten.
Es ist eine gute Idee, ein Satz von Standardtrics 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 Festschreiben zu Festschreiben ähnlich bleiben, können Sie Binärdeltas insgesamt 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 es eine Alles-oder-Nichts-Einstellung, die sich auch auf Ihren Quellcode auswirkt.
Möglicherweise möchten Sie Teile von OTABS mit Skripts versehen, um eine schnellere Verwendung zu ermöglichen. Insbesondere die Scripting-Schritte 2-3 von Vollständiges Löschen von Binärdateien in einem update
Git-Hook könnten eine überzeugende, aber möglicherweise gefährliche Semantik für git fetch ("alles holen und löschen, was das ist ist nicht mehr aktuell").
Möglicherweise möchten Sie Schritt 4 von Vollständiges Löschen von Binärdateien überspringen, um einen vollständigen Verlauf aller binären Änderungen auf der Fernbedienung auf Kosten des zentralen Repositorys zu erhalten. Lokale Repositories bleiben im Laufe der Zeit mager.
In Java world ist es möglich, diese Lösung mit maven --offline
Zu kombinieren, um einen reproduzierbaren Offline-Build zu erstellen, der vollständig in Ihrer Versionskontrolle gespeichert ist (mit maven ist es einfacher als mit gradle) Weltweit ist es möglich, auf dieser Lösung aufzubauen, um GOPATH anstelle von go get
zu verwalten. In python Weltweit 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 sich Ihre Binärdateien sehr oft ändern, wie z. B. beim Erstellen von Artefakten, ist es möglicherweise eine gute Idee, ein Skript zu erstellen, in dem die fünf neuesten Versionen der Artefakte in den Orphan-Tags monday_bin
, tuesday_bin
, Gespeichert werden. .., friday_bin
Und außerdem ein Orphan-Tag für jede Veröffentlichung 1.7.8bin
2.0.0bin
Usw. Sie können den weekday_bin
Drehen und alte Binärdateien täglich löschen. Auf diese Weise erhalten Sie das Beste aus zwei Welten: Sie behalten den gesamten Verlauf Ihres Quellcodes bei, 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 seiner gesamten Historie abzurufen: git init && git remote add <name> <url> && git fetch <name> <tag>
Sollte reichen es für dich.
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 ich eine JPEG-Datei hinzugefügt und viermal um 90 Grad gedreht habe (um die Wirksamkeit zu überprüfen) von binären Deltas). Das Repository von Git wuchs um 400%. Das Repository von SVN wuchs nur um 11%.
Es sieht also so aus, als wäre SVN mit Binärdateien viel effizienter.
Ich wähle Git für den Quellcode und SVN für Binärdateien wie Dokumentation.
git clone --filter
ab Git 2.19 + flache Klone
Diese neue Option könnte schließlich die endgültige Lösung des Problems mit Binärdateien werden, wenn die Entwickler von Git und GitHub es benutzerfreundlich genug machen (was sie wohl für Submodule immer noch nicht erreicht haben zum Beispiel).
Es erlaubt eigentlich 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önnen 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 schon ein --filter=blob:limit<size>
, mit dem die maximale Größe der abzurufenden Blobs begrenzt werden kann.
Ich habe ein minimales detailliertes Beispiel für das Aussehen der Funktion angegeben: Wie klone ich nur ein Unterverzeichnis eines Git-Repositorys?
Ich suche 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 bin mit einigen meiner Cloud-Hosts auf Synchronisationsfehler mit Git gestoßen, nachdem die Binärdaten meiner Webanwendungen über der Marke von 3 GB eingekerbt wurden. Ich dachte damals an BFT Repo Cleaner , aber es fühlte sich wie ein Hack an. Seitdem habe ich angefangen, Dateien nur außerhalb von Git zu behalten, stattdessen speziell entwickelte Tools wie Amazon S3 für die Verwaltung von Dateien, die Versionsverwaltung und die Sicherung zu verwenden.
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 wenig kitschig, aber es erledigt die Arbeit.
Mein Vorschlag ist, das richtige Werkzeug für den Job zu wählen. Wenn es für ein Unternehmen ist und Sie Ihre Codeline auf GitHub verwalten, zahlen Sie das Geld und verwenden Sie Git-LFS. Andernfalls könnten Sie kreativere Optionen wie dezentrales, verschlüsseltes Dateispeicherung mit Blockchain ausprobieren.
Zusätzliche zu berücksichtigende Optionen sind Minio und s3cmd .