57 Stimmen

Git mit großen Dateien

Situation

Ich habe zwei Server, Produktion und Entwicklung. Auf dem Produktionsserver gibt es zwei Anwendungen und mehrere (6) Datenbanken (MySQL), die ich Entwicklern zum Testen zur Verfügung stellen muss. Alle Quellcodes sind auf GitLab auf dem Entwicklungsserver gespeichert, und die Entwickler arbeiten nur mit diesem Server und haben keinen Zugriff auf den Produktionsserver. Wenn wir eine Anwendung veröffentlichen, meldet sich der Master auf der Produktionsseite an und zieht die neue Version von Git. Die Datenbanken sind groß (jeweils über 500M und zählend) und ich muss sie so einfach wie möglich an Entwickler für Tests verteilen.

Mögliche Lösungen

  • Nach einem Sicherungsskript, das Datenbanken dumppt, jeder in eine einzelne Datei, führen Sie ein Skript aus, das jede Datenbank in ihren eigenen Zweig schiebt. Ein Entwickler zieht einen dieser Zweige, wenn er seine lokale Kopie aktualisieren möchte.

    Diese Lösung funktionierte nicht.

  • Cron auf dem Produktionsserver speichert täglich Binärprotokolle und schiebt sie in den Zweig dieser Datenbank. Auf diese Weise gibt es im Zweig Dateien mit täglichen Änderungen, und der Entwickler zieht die Dateien, die er nicht hat. Der aktuelle SQL-Dump wird auf andere Weise an den Entwickler gesendet. Und wenn die Größe des Repositories zu groß wird, senden wir einen vollständigen Dump an die Entwickler und löschen alle Daten im Repository und starten von vorne.

Fragen

  • Ist die Lösung möglich?
  • Wenn git in das Repository pusht/pullt, lädt es dann ganze Dateien hoch/runter oder nur Änderungen darin (d.h. fügt neue Zeilen hinzu oder bearbeitet die aktuellen)?
  • Kann Git mit so großen Dateien umgehen? Nein.
  • Wie kann man festlegen, wie viele Revisionen in einem Repository aufbewahrt werden? Mit der neuen Lösung spielt das keine Rolle.
  • Gibt es eine bessere Lösung? Ich möchte die Entwickler nicht zwingen, solch große Dateien über FTP oder ähnliches herunterzuladen.

32voto

Amber Punkte 473552

Sie möchten wirklich, wirklich, wirklich nicht, dass große Binärdateien in Ihr Git-Repository eingecheckt werden.

Jedes Update, das Sie hinzufügen, trägt kumulativ zur Gesamtgröße Ihres Repositories bei, was bedeutet, dass Ihr Git-Repo im Laufe der Zeit immer länger zum Klonen benötigt und immer mehr Festplattenspeicher verbraucht, da Git die gesamte Historie des Zweigs lokal speichert, was bedeutet, dass wenn jemand den Zweig auscheckt, sie nicht nur die neueste Version der Datenbank herunterladen müssen; sie müssen auch jede vorherige Version herunterladen.

Wenn Sie große Binärdateien bereitstellen müssen, laden Sie sie separat auf einen Server hoch und checken Sie dann eine Textdatei mit einer URL ein, über die der Entwickler die große Binärdatei herunterladen kann. FTP ist tatsächlich eine der besseren Optionen, da es speziell für die Übertragung von Binärdateien konzipiert ist, obwohl HTTP wahrscheinlich noch geradliniger ist.

31voto

PeterSW Punkte 4580

rsync könnte eine gute Option sein, um die Kopien der Entwicklerdatenbanken effizient zu aktualisieren.

Es verwendet einen Delta-Algorithmus, um die Dateien inkrementell zu aktualisieren. Auf diese Weise werden nur die geänderten oder neuen Dateiblöcke übertragen. Natürlich müssen sie die vollständige Datei zunächst herunterladen, aber spätere Updates wären schneller.

Im Wesentlichen erhalten Sie ein ähnliches inkrementelles Update wie ein git fetch, ohne die ständig wachsende anfängliche Kopie, die das git clone liefern würde. Der Verlust besteht darin, dass Sie die Historie nicht haben, aber es klingt so, als ob Sie das nicht brauchen.

rsync ist ein Standardbestandteil der meisten Linux-Distributionen. Wenn Sie es auf Windows benötigen, steht ein verpackter Port zur Verfügung: http://itefix.no/cwrsync/

Um die Datenbanken an einen Entwickler zu übertragen, könnten Sie einen Befehl ähnlich wie diesen verwenden:

rsync -avz Pfad/zur/Datenbank(en) HOST:/Ordner

Oder die Entwickler könnten die benötigten Datenbank(en) abrufen mit:

rsync -avz DATABASE_HOST:/Pfad/zur/Datenbank(en) Pfad/wo/der/Entwickler/es/haben/möchte

26voto

VonC Punkte 1117238

Sie können sich Lösungen wie git-annex ansehen, die sich mit der Verwaltung von (großen) Dateien mit git beschäftigen, ohne die Dateiinhalte in git einzuchecken(!)
(Feb 2015: Ein Service-Hosting wie GitLab integriert es nativ:
Siehe "Unterstützt GitLab große Dateien über git-annex oder anderweitig?")

git verwaltet keine großen Dateien, wie von Amber in ihrer Antwort erklärt.

Das bedeutet jedoch nicht, dass git eines Tages nicht besser sein wird.
Von GitMinutes Episode 9 (Mai 2013, siehe auch unten), von Peff (Jeff King), bei 36'10'':

(Transkript)

Es gibt eine ganz andere Welt großer Repositories, in der die Leute daran interessiert sind, 20 oder 30 oder 40 GB, manchmal sogar TB-große Repositories zu speichern, und ja, das kommt vom Vorhandensein einer Menge Dateien, aber ein Großteil stammt von wirklich großen Dateien und wirklich großen binären Dateien, die nicht so gut miteinander umgehen.

Das ist sozusagen ein offenes Problem. Es gibt ein paar Lösungen: git-annex ist wahrscheinlich die ausgereifteste davon, bei der sie im Grunde genommen das Asset nicht in git legen, sondern das große Asset auf einem Asset-Server ablegen und einen Zeiger in git setzen.

Ich würde gerne so etwas machen, wo das Asset konzep tionell in git liegt, d. h. die SHA1 dieses Objekts ist Teil des SHA1, der in den Baum, der in die Commit-ID und all diese Dinge eingeht.
Also aus der Perspektive von git ist es Teil des Repositories, aber auf einer tieferen Ebene, auf der Objektspeicherebene, auf einer Ebene unterhalb des konzep t ionellen Verlaufsbildes, wo wir bereits mehrere Möglichkeiten haben, ein Objekt zu speichern: Wir haben lose Objekte, wir haben gepackte Objekte, ich hätte vielleicht gerne eine neue Möglichkeit, ein Objekt zu speichern, die besagt "wir haben es hier nicht, aber es ist über einen Asset-Server verfügbar", oder so etwas.

(Thomas Ferris Nicolaisen) Oh cool...

Das Problem bei Dingen wie git-annex ist: Wenn Sie sie einmal benutzen, sind Sie ... für immer an die Entscheidungen gebunden, die Sie zu diesem Zeitpunkt getroffen haben. Sie wissen, dass Sie sich entscheiden können, oh, 200 MB sind groß, und wir werden sie auf einem Asset-Server speichern, und dann entscheiden Sie später, dass es doch 300 MB hätte sein sollen, naja, Pech gehabt: das ist für immer in Ihrer Geschichte codiert.
Und indem Sie konzep t ionell auf Ebene von git sagen, dass dieses Objekt im git-Repository ist, nicht irgendein Zeiger darauf, nicht ein Zeiger auf einen Asset-Server, das tatsächliche Objekt ist da, und dann sich um diese Details auf niedriger Ebene, auf der Speicherebene, kümmern, dann sind Sie frei, viele verschiedene Entscheidungen zu treffen und sogar Ihre Entscheidung später darüber zu ändern, wie Sie die Daten tatsächlich auf der Festplatte speichern möchten.

Derzeit kein Projekt mit hoher Priorität ...


3 Jahre später, im April 2016, enthält Git Minutes 40 ein Interview mit Michael Haggerty von GitHub um 31' (Danke Christian Couder für das Interview).

Er ist schon seit geraumer Zeit auf Referenz-Backends spezialisiert, wie in spezialisiert.
Er zitiert
David Turners Arbeit an Back-End als derzeit interessantsten. (Siehe Davids aktuellen "pluggable-backends"-Zweig seiner git/git-Fork))

(Transkript)

Christian Couder (CD): Das Ziel ist es, Git-Referenzen in einer Datenbank zu speichern, zum Beispiel? Michael Haggerty (MH): Ja, ich sehe darin zwei interessante Aspekte: Der erste besteht einfach darin, die Möglichkeit zu haben, verschiedene Quelleintrag-Referenzen zu integrieren. Eintrag-Referenzen werden im Dateisystem gespeichert, als Kombination aus lose Referenzen und gepackten Referenzen.
Loose-Referenz ist eine Datei pro Referenz, und gepackte Referenz ist eine große Datei, die eine Liste vieler vieler Referenzen enthält.

Das ist ein gutes System, vor allem für den lokalen Gebrauch; es hat keine echten Leistungsprobleme für normale Menschen, aber es hat einige Probleme, z.B. können Sie Referenz-Reflogs nicht speichern, nachdem die Referenzen gelöscht wurden, da Konflikte mit neueren Referenzen auftreten können, die mit ähnlichen Namen erstellt wurden. Es besteht auch ein Problem darin, dass Referenznamen im Dateisystem gespeichert sind, sodass Sie Referenzen haben können, die ähnlich benannt sind, aber mit unterschiedlicher Großschreibung.
Diese Dinge könnten also durch ein allgemeines Referenz-Back-End-System behoben werden.
Der andere Aspekt von David Turners Patchserie ist eine Änderung, Referenzen in einer Datenbank namens lmdb zu speichern, das ist eine wirklich schnelle speicherbasierte Datenbank, die einige Leistungsvorteile gegenüber dem Datei-Backend hat.

[folgen weitere Überlegungen zur schnelleren Packung und Anzeigen von Referenzpatches]

2voto

Alex North-Keys Punkte 4031

Eine Hilfsspeicherung von Dateien, die von Ihrem git-gestashten Code referenziert werden, ist der Weg, den die meisten Menschen gehen. git-annex sieht ziemlich umfassend aus, aber viele Unternehmen verwenden einfach ein FTP- oder HTTP-(oder S3)-Repository für die großen Dateien, wie SQL-Dumps. Mein Vorschlag wäre, den Code im Git-Repo mit den Namen der Dateien im Hilfsspeicher zu verknüpfen, indem einige Metadaten - insbesondere eine Prüfsumme (wahrscheinlich SHA) - in den Hash eingefügt werden, sowie ein Datum.

  • Jede Hilfsdatei erhält also einen Stammnamen, ein Datum und eine SHA(für eine bestimmte Version n)-Summe.
  • Wenn Sie eine hohe Dateianzahl haben, stellt die Verwendung nur eines SHA eine geringfügige, aber reale Bedrohung durch Hash-Kollision dar, weshalb das Datum (Epochenzeit oder ISO-Datum) eingeschlossen wird.
  • Fügen Sie den resultierenden Dateinamen in den Code ein, damit der Hilfsteil ganz spezifisch durch Verweis eingebunden wird.
  • Strukturieren Sie die Namen so, dass ganz einfach ein Skript geschrieben werden kann, um mit git grep alle Hilfsdateinamen zu suchen, sodass die Liste für jeden Commit leicht zu erhalten ist. Dies ermöglicht auch, dass die alten Dateien zu einem bestimmten Zeitpunkt außer Betrieb genommen werden können, und kann mit dem Bereitstellungssystem integriert werden, um die neuen Hilfsdateien vor der Aktivierung des Codes aus dem Git-Repo auf die Produktion zu ziehen, ohne die alten zu überschreiben (noch nicht).

Das Stopfen riesiger Dateien in git (oder die meisten Repositories) hat nach einer Weile einen unangenehmen Einfluss auf die Leistung von git - ein git clone sollte wirklich nicht zwanzig Minuten dauern, zum Beispiel. Wenn jedoch die Dateien per Verweis verwendet werden, bedeutet dies, dass einige Entwickler die großen Blöcke überhaupt nie herunterladen müssen (im scharfen Gegensatz zum git clone), da die Wahrscheinlichkeit besteht, dass die meisten nur für den bereitgestellten Code in der Produktion relevant sind. Ihre Erfahrungen mögen natürlich abweichen.

0voto

Ariful Islam Punkte 566

Große Dateien hochladen verursachen manchmal Probleme und Fehler. Das passiert normalerweise. In der Regel unterstützt git Dateien von weniger als 50 MB zum Hochladen. Um Dateien von mehr als 50 MB im Git-Repository hochzuladen, muss der Benutzer einen anderen Assistenten installieren, der beim Hochladen großer Dateien (.mp4, .mp3, .psd) usw. hilft.

Es gibt einige grundlegende git-Befehle, die Sie kennen sollten, bevor Sie große Dateien in git hochladen. Dies ist die Konfiguration für das Hochladen bei github. Es muss gitlfs.exe installiert werden

Installieren Sie es von lfsinstall.exe

Dann sollten Sie grundlegende Git-Befehle zusammen mit einigen anderen verwenden

git lfs install
git init
git lfs track ".mp4"
git lfs track ".mp3"
git lfs track ".psd"
git add .
git add .gitattributes
git config lfs.https://github.com/something/repo.git/info/lfs.locksverify false 
git commit -m "Designdatei hinzufügen"
git push origin master` ones

Sie werden möglicherweise während des push-Befehls Anweisungen wie lfs.https://github.com/something/repo.git/info/lfs.locksverify false finden, wenn Sie ohne sie pushen

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X