Question Gérer de gros fichiers binaires avec Git


Je cherche des avis sur la façon de gérer les gros fichiers binaires sur lesquels dépend mon code source (application web). Nous discutons actuellement plusieurs alternatives:

  1. Copiez les fichiers binaires à la main.
    • Pro: Pas sûr
    • Contra: Je suis fortement contre, car cela augmente la probabilité d'erreurs lors de la mise en place d'un nouveau site / migration de l'ancien. Construit un autre obstacle à prendre.
  2. Gérer tous avec Git.
    • Pro: Supprime la possibilité d''oublier' de copier un fichier important
    • Contre: Bloats le référentiel et diminue la flexibilité pour gérer la base de code et les extractions, clones, etc. prendront un certain temps.
  3. Référentiels séparés.
    • Pro: l'extraction / le clonage du code source est rapide et les images sont correctement archivées dans leur propre référentiel.
    • Contra: Supprime la simplicité d'avoir le seul et unique Git référentiel sur le projet. Cela introduit sûrement d'autres choses auxquelles je n'ai pas pensé.

Quelles sont vos expériences / pensées à ce sujet?

En outre: Quelqu'un at-il de l'expérience avec plusieurs référentiels Git et les gérer dans un projet?

Les fichiers sont des images pour un programme qui génère des fichiers PDF avec ces fichiers. Les fichiers ne changeront pas très souvent (comme en années), mais ils sont très pertinents pour un programme. Le programme ne fonctionnera pas sans les fichiers.


507
2018-02-12 08:52


origine


Réponses:


Si le programme ne fonctionne pas sans les fichiers, cela semble être une mauvaise idée de les diviser en un dépôt séparé. Nous avons de grandes suites de tests que nous divisons en un dépôt séparé, mais ce sont vraiment des fichiers "auxiliaires".

Cependant, vous pourrez peut-être gérer les fichiers dans un rapport séparé, puis utiliser git-submodule pour les intégrer dans votre projet d'une manière saine. Donc, vous avez toujours l'historique complet de toutes vos sources, mais si je comprends bien, vous ne disposez que de la seule révision pertinente de votre sous-module images. le git-submodule Facilité devrait vous aider à garder la version correcte du code en ligne avec la version correcte des images.

Voici un bon introduction aux sous-modules de Git Book.


173
2018-02-12 14:29



J'ai découvert annexe de git récemment que je trouve génial. Il a été conçu pour gérer efficacement les fichiers volumineux. Je l'utilise pour mes collections photo / musique (etc.). Le développement de git-annex est très actif. Le contenu des fichiers peut être supprimé du référentiel Git, seule la hiérarchie de l’arbre est suivie par Git (via des liens symboliques). Cependant, pour obtenir le contenu du fichier, une deuxième étape est nécessaire après avoir tiré / poussé, par exemple:

$ 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

Il existe de nombreuses commandes disponibles, et il existe une excellente documentation sur le site Web. Un paquet est disponible sur Debian.


305
2017-07-09 13:54



Une autre solution, depuis avril 2015 est Git Large File Storage (LFS) (par GitHub).

Il utilise git-lfs (voir git-lfs.github.com) et testé avec un serveur le supportant: lfs-test-server:
Vous pouvez stocker des métadonnées uniquement dans le repo git et le fichier volumineux ailleurs.

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


41
2018-04-09 05:53



Jettes un coup d'oeil à git bup qui est une extension Git pour stocker intelligemment de gros fichiers binaires dans un dépôt Git.

Vous voudriez l'avoir comme sous-module, mais vous n'aurez pas à vous inquiéter du fait que le référentiel devienne difficile à gérer. L'un de leurs exemples d'utilisation est le stockage des images de machine virtuelle dans Git.

Je n'ai pas vraiment vu de meilleurs taux de compression, mais mes référentiels ne contiennent pas de fichiers binaires très volumineux.

Votre kilométrage peut varier.


29
2018-03-21 21:59



Vous pouvez aussi utiliser git-fat. J'aime que cela ne dépend que du stock de python et rsync. Il prend également en charge le flux de production Git habituel, avec les commandes suivantes:

git fat init
git fat push
git fat pull

En outre, vous devez archiver un fichier .gitfat dans votre référentiel et modifier vos attributs .gitat pour spécifier les extensions de fichier souhaitées. git fat gérer.

Vous ajoutez un binaire en utilisant la normale git add, qui à son tour invoque git fat en fonction de vos règles gitattributes.

Enfin, il présente l'avantage que l'emplacement où vos fichiers binaires sont réellement stockés peut être partagé entre les référentiels et les utilisateurs et prend en charge tout rsync Est-ce que.

MISE À JOUR: N'utilisez pas git-fat si vous utilisez un bridge Git-SVN. Il finira par supprimer les fichiers binaires de votre dépôt Subversion. Cependant, si vous utilisez un référentiel Git pur, il fonctionne parfaitement.


26
2017-09-26 04:51



J'utiliserais des sous-modules (comme Pat Notz) ou deux référentiels distincts. Si vous modifiez trop souvent vos fichiers binaires, j'essaierais de minimiser l'impact de l'immense référentiel en nettoyant l'historique:

J'ai eu un problème très similaire il y a plusieurs mois: ~ 21 Go de fichiers MP3, non classés (mauvais noms, mauvais id3, je ne sais pas si j'aime ce fichier MP3 ou non ...), et répliqués sur trois ordinateurs.

J'ai utilisé un disque dur externe avec le dépôt Git principal et je l'ai cloné dans chaque ordinateur. Ensuite, j'ai commencé à les classer de la manière habituelle (pousser, tirer, fusionner ... supprimer et renommer plusieurs fois).

À la fin, je n'avais que ~ 6 Go de fichiers MP3 et ~ 83 Go dans le répertoire .git. j'ai utilisé git-write-tree et git-commit-tree pour créer une nouvelle validation, sans ancêtres de validation, et a démarré une nouvelle branche pointant vers cette validation. Le "git log" pour cette branche ne montrait qu'un seul commit.

Ensuite, j'ai supprimé l'ancienne branche, gardé seulement la nouvelle branche, supprimé les ref-logs, et lancez "git prune": après cela, mes dossiers .git ne pesaient que ~ 6 Go ...

De temps en temps, vous pouvez "purger" l'énorme dépôt de la même manière: votre "clone git" sera plus rapide.


21
2018-02-12 14:52



À mon avis, si vous êtes susceptible de modifier souvent ces gros fichiers, ou si vous avez l’intention de faire beaucoup de git clone ou git checkout, alors vous devriez envisager sérieusement d'utiliser un autre dépôt Git (ou peut-être un autre moyen d'accéder à ces fichiers).

Mais si vous travaillez comme nous, et si vos fichiers binaires ne sont pas souvent modifiés, alors le premier clonage / checkout sera long, mais après cela il devrait être aussi rapide que vous voulez (en considérant vos utilisateurs continuent à utiliser le premier référentiel cloné avait).


12
2018-02-12 09:12



La solution que je voudrais proposer est basée sur des branches orphelines et un léger abus du mécanisme de balises, désormais dénommé * Orphan Tags Binary Storage (OTABS)

TL; DR 12-01-2017 Si vous pouvez utiliser LFS de github ou une autre tierce partie, vous devez absolument le faire. Si vous ne pouvez pas, alors lisez la suite. Soyez averti, cette solution est un hack et devrait être traitée comme telle.

Propriétés souhaitables d'OTABS

  • c'est un pur git et git seulement solution - il fait le travail sans aucun logiciel tiers (comme git-annexe) ou une infrastructure tierce (comme LFS de github).
  • il stocke les fichiers binaires efficacementc'est-à-dire qu'il ne gonfle pas l'historique de votre dépôt.
  • git pull et git fetch, comprenant git fetch --all sont encore bande passante efficacec'est-à-dire que tous les fichiers binaires volumineux ne sont pas retirés de la télécommande par défaut.
  • ça marche les fenêtres.
  • il stocke tout dans un dépôt git unique.
  • ça permet effacement de binaires obsolètes (contrairement à bup).

Propriétés indésirables des OTABS

  • cela fait git clone potentiellement inefficace (mais pas nécessairement, selon votre utilisation). Si vous déployez cette solution, vous devrez peut-être conseiller à vos collègues d'utiliser git clone -b master --single-branch <url> au lieu de git clone. C'est parce que git clone par défaut clone littéralement tout référentiel, y compris les éléments sur lesquels vous ne voudriez normalement pas gaspiller votre bande passante, comme les commits non référencés. Pris à partir de SO 4811434.
  • cela fait git fetch <remote> --tags bande passante inefficace, mais pas nécessairement inefficace de stockage. Vous pouvez toujours conseiller à vos collègues de ne pas l'utiliser.
  • vous devrez utiliser périodiquement un git gc astuce pour nettoyer votre dépôt de tous les fichiers que vous ne voulez plus.
  • ce n'est pas aussi efficace que bup ou git-bigfiles. Mais il est respectivement plus adapté à ce que vous essayez de faire et plus disponible sur le marché. Vous risquez de rencontrer des problèmes avec des centaines de milliers de petits fichiers ou avec des fichiers de plusieurs giga-octets, mais lisez la suite pour trouver des solutions.

Ajouter les fichiers binaires

Avant de commencer, assurez-vous d'avoir validé toutes vos modifications, votre arborescence est à jour et votre index ne contient aucune modification non validée. Il peut être judicieux de transférer toutes vos succursales locales vers votre télécommande (github, etc.) au cas où une catastrophe surviendrait.

  1. Créez une nouvelle branche orpheline. git checkout --orphan binaryStuff fera l'affaire. Cela produit une branche qui est entièrement déconnectée de toute autre branche, et le premier commit que vous ferez dans cette branche n'aura pas de parent, ce qui en fera un commit racine.
  2. Nettoyez votre index en utilisant git rm --cached * .gitignore.
  3. Respirez profondément et supprimez tout l'arbre de travail en utilisant rm -fr * .gitignore. Interne .git répertoire restera intact, parce que le * Le caractère générique ne correspond pas.
  4. Copiez dans votre VeryBigBinary.exe ou votre VeryHeavyDirectory /.
  5. Ajoutez-le && commit.
  6. Maintenant, cela devient difficile - si vous l'insérez dans la télécommande en tant que branche, tous vos développeurs le téléchargeront la prochaine fois qu'ils invoqueront git fetchobstruer leur connexion. Vous pouvez éviter cela en poussant une balise au lieu d'une branche. Cela peut toujours avoir un impact sur la bande passante et le stockage du système de fichiers de vos collègues s'ils ont l'habitude de taper git fetch <remote> --tags, mais lisez la suite pour une solution de contournement. Allez-y et git tag 1.0.0bin
  7. Poussez votre tag orphelin git push <remote> 1.0.0bin.
  8. Juste pour que vous ne poussez jamais votre branche binaire par accident, vous pouvez le supprimer git branch -D binaryStuff. Votre commit ne sera pas marqué pour le garbage collection, car une balise orpheline pointant dessus 1.0.0bin est suffisant pour le garder en vie.

Extraire le fichier binaire

  1. Comment puis-je (ou mes collègues) obtenir le VeryBigBinary.exe extrait dans l'arborescence de travail actuelle? Si votre branche de travail actuelle est par exemple maître, vous pouvez simplement git checkout 1.0.0bin -- VeryBigBinary.exe.
  2. Cela échouera si vous n'avez pas la balise orpheline 1.0.0bin téléchargé, auquel cas vous devrez git fetch <remote> 1.0.0bin préalablement.
  3. Vous pouvez ajouter le VeryBigBinary.exe dans votre maître .gitignore, afin que personne dans votre équipe ne pollue l’historique principal du projet avec le binaire par accident.

Suppression complète du fichier binaire

Si vous décidez de purger complètement VeryBigBinary.exe de votre référentiel local, votre référentiel distant et les référentiels de votre collègue, vous pouvez simplement:

  1. Supprimer l'étiquette orpheline sur la télécommande git push <remote> :refs/tags/1.0.0bin
  2. Supprimer le tag orphelin localement (supprime tous les autres tags non référencés) git tag -l | xargs git tag -d && git fetch --tags. Pris à partir de SO 1841341 avec une légère modification.
  3. Utilisez une astuce git gc pour supprimer votre commit maintenant non référencé localement. git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc "$@". Il supprimera également tous les autres commits non référencés. Pris à partir de SO 1904860
  4. Si possible, répétez l'astuce git gc sur la télécommande. Il est possible que vous hébergiez vous-même votre référentiel et que cela ne soit pas possible avec certains fournisseurs git, comme github ou dans certains environnements d'entreprise. Si vous hébergez chez un fournisseur qui ne vous donne pas l'accès ssh à la télécommande, laissez-le. Il est possible que l'infrastructure de votre fournisseur nettoie votre commit non référencé dans son propre temps doux. Si vous êtes dans un environnement d'entreprise, vous pouvez conseiller votre service informatique pour exécuter une tâche cron de collecte de votre télécommande une fois par semaine. Qu'ils le fassent ou non, votre équipe n'aura aucun impact en termes de bande passante et de stockage, à condition que vous conseilliez toujours à vos collègues git clone -b master --single-branch <url> au lieu de git clone.
  5. Tous vos collègues qui veulent se débarrasser des balises orphelines obsolètes doivent seulement appliquer les étapes 2-3.
  6. Vous pouvez ensuite répéter les étapes 1-8 de Ajouter les fichiers binaires créer une nouvelle balise orpheline 2.0.0bin. Si vous êtes inquiet au sujet de vos collègues qui tapent git fetch <remote> --tags vous pouvez réellement le nommer à nouveau 1.0.0bin. Cela fera en sorte que la prochaine fois qu'ils vont chercher tous les tags de l'ancien 1.0.0bin sera non référencé et marqué pour la collecte ultérieure des ordures (en utilisant l'étape 3). Lorsque vous essayez d'écraser une étiquette sur la télécommande, vous devez utiliser -f comme ça: git push -f <remote> <tagname>

Épilogue

  • OTABS ne touche pas votre maître ni aucun autre code source / branche de développement. Les hachages de validation, l'ensemble de l'historique et la petite taille de ces branches ne sont pas affectés. Si vous avez déjà gonflé votre historique de code source avec des fichiers binaires, vous devrez le nettoyer en un morceau de travail distinct. Ce script pourrait être utile.

  • Confirmé pour travailler sur Windows avec git-bash.

  • C'est une bonne idée d'appliquer un ensemble de trics standard rendre plus efficace le stockage des fichiers binaires. Le fonctionnement fréquent de git gc (sans aucun argument supplémentaire), git optimise le stockage sous-jacent de vos fichiers en utilisant des deltas binaires. Cependant, s'il est peu probable que vos fichiers restent similaires à commit, vous pouvez désactiver complètement les deltas binaires. De plus, parce que cela n'a aucun sens de compresser des fichiers déjà compressés ou cryptés, comme .zip, .jpg ou .crypt, git vous permet de désactiver la compression du stockage sous-jacent. Malheureusement, c'est un paramètre tout ou rien qui affecte également votre code source.

  • Vous voudrez peut-être créer des scripts pour certaines parties d’OTABS afin de permettre une utilisation plus rapide. En particulier, les étapes de script 2-3 de Suppression complète des fichiers binaires dans un update git hook pourrait donner une sémantique convaincante mais peut-être dangereuse à git fetch ("récupérer et supprimer tout ce qui est périmé").

  • Vous pouvez passer l'étape 4 de Suppression complète des fichiers binaires pour garder un historique complet de tous les changements binaires sur la télécommande au détriment de la surcharge du référentiel central. Les dépôts locaux resteront au fil du temps.

  • Dans le monde Java, il est possible de combiner cette solution avec maven --offline pour créer une version hors ligne reproductible stockée entièrement dans votre contrôle de version (c'est plus facile avec maven qu'avec gradle). Dans le monde Golang, il est possible de construire sur cette solution pour gérer votre GOPATH au lieu de go get. Dans le monde python, il est possible de combiner ceci avec virtualenv pour produire un environnement de développement autonome sans compter sur les serveurs PyPi pour chaque génération à partir de zéro.

  • Si vos fichiers binaires changent très souvent, comme les artefacts de construction, il peut être judicieux de programmer une solution qui stocke les 5 versions les plus récentes des artefacts dans les balises orphelines monday_bin, tuesday_bin, ..., friday_bin, et aussi une balise orpheline pour chaque version 1.7.8bin  2.0.0bin, etc. Vous pouvez faire pivoter le weekday_bin et supprime les anciens binaires tous les jours. De cette façon, vous obtenez le meilleur des deux mondes: vous gardez le tout l'historique de votre code source, mais seulement pertinent l'historique de vos dépendances binaires. Il est également très facile d'obtenir les fichiers binaires pour un tag donné sans pour autant obtenir le code source complet avec toute son histoire: git init && git remote add <name> <url> && git fetch <name> <tag> devrait le faire pour vous.


11
2017-07-13 18:32



SVN semble gérer les deltas binaires plus efficacement que Git.

J'ai dû choisir un système de gestion des versions pour la documentation (fichiers JPEG, fichiers PDF et fichiers .odt). Je viens de tester l'ajout d'un fichier JPEG et de le faire pivoter de 90 degrés quatre fois (pour vérifier l'efficacité des deltas binaires). Le dépôt de Git a augmenté de 400%. Le dépôt de SVN n'a augmenté que de 11%.

Donc, il semble que SVN est beaucoup plus efficace avec les fichiers binaires.

Donc, mon choix est Git pour le code source et SVN pour les fichiers binaires comme la documentation.


8
2017-10-03 03:11