529 votes

Gérer les gros fichiers binaires avec Git

Je cherche des avis sur la manière de traiter les gros fichiers binaires dont dépend mon code source (application web). Nous sommes en train de discuter de plusieurs alternatives :

  1. Copiez les fichiers binaires à la main.
    • Pro : Pas sûr.
    • Contre : 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. Cela crée un obstacle supplémentaire à franchir.
  2. Gérez-les tous avec Git .
    • Pro : Supprime la possibilité d'oublier de copier un fichier important.
    • Contra : Bloque le dépôt et diminue la flexibilité pour gérer la base de code et les checkouts, clones, etc. prendront un certain temps.
  3. Dépôts séparés.
    • Pro : L'extraction/le clonage du code source est plus rapide que jamais, et les images sont correctement archivées dans leur propre dépôt.
    • Contra : Enlève la simplicité d'avoir le seul et unique Dépôt Git sur le projet. Cela introduit sûrement d'autres choses auxquelles je n'ai pas pensé.

Quelles sont vos expériences/réflexions à ce sujet ?

Aussi : Quelqu'un a-t-il de l'expérience avec plusieurs dépôts Git et leur gestion dans un seul projet ?

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

26 votes

Qu'en est-il lorsque le contrôle de version du fichier binaire est nécessaire ? Je pense à des équipes d'artistes travaillant sur des ressources.

3 votes

Si c'est nécessaire, vous devez mettre en balance vos ressources disponibles (disque, bande passante, temps CPU) et le bénéfice que vous en tirez.

4 votes

Notez que sans verrouillage des fichiers, git n'est pas idéal lorsque plusieurs personnes doivent travailler sur le même fichier binaire.

312voto

rafak Points 3310

J'ai découvert git-annex récemment, ce que je trouve génial. Il a été conçu pour gérer efficacement les gros fichiers. Je l'utilise pour mes collections de photos/musiques (etc.). Le développement de git-annex est très actif. Le contenu des fichiers peut être supprimé du dépôt Git, seule la hiérarchie de l'arbre est suivie par Git (grâce aux liens symboliques). Cependant, pour obtenir le contenu du fichier, une deuxième étape est nécessaire après le pulling/pushing, par ex :

$ 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 y a de nombreuses commandes disponibles, et une excellente documentation sur le site web. Un paquet est disponible sur Debian .

12 votes

Whoa ! Upvote pour la génialité ! Ceci implémente une idée que j'ai eue récemment, et bien plus encore. C'est écrit en Haskell, pas moins. git-media est une bonne alternative, d'ailleurs.

0 votes

Les sous-modules prêtent à confusion et il est facile de se "perdre" en les utilisant. L'annexe semble être une bien meilleure solution à ce problème.

34 votes

Mais, l'annexe ne supporte pas Windows. Ce qui est problématique pour les développeurs de jeux.

178voto

Pat Notz Points 46841

Si le programme ne fonctionne pas sans les fichiers, il semble que les séparer dans un dépôt séparé soit une mauvaise idée. Nous avons de grandes suites de tests que nous séparons dans un dépôt séparé, mais ce sont vraiment des fichiers "auxiliaires".

Cependant, il est possible de gérer les fichiers dans un dépôt séparé, puis d'utiliser la fonction git-submodule pour les attirer dans votre projet d'une manière saine. Ainsi, vous auriez toujours l'historique complet de toutes vos sources mais, si je comprends bien, vous n'auriez que la seule révision pertinente de votre sous-module images. Le site git-submodule devrait vous aider à garder la bonne version du code en ligne avec la bonne version des images.

Voici un bon introduction aux submodules de Git Book.

12 votes

"Si je comprends bien, vous n'auriez que la seule révision pertinente de votre sous-module images." Je ne pense pas que ce soit correct.

24 votes

En effet. Un sous-module est un dépôt Git complet, qui se trouve juste être imbriqué dans le dépôt parent. Il connaît tout son historique. Vous pouvez y commettre moins fréquemment, mais si vous y stockez les mêmes choses que vous auriez dans le parent, il aura les mêmes problèmes que le parent.

5 votes

C'est une solution plutôt médiocre si vous avez de gros fichiers binaires qui changent à un intervalle régulier. Nous avons un référentiel qui est horriblement gonflé parce qu'un nouveau fichier binaire y est stocké à chaque construction. Si vous n'êtes pas sous Windows, comme mentionné ci-dessous, Annex est une bonne solution. Si vous êtes sous Windows... il faudra continuer à chercher.

33voto

sehe Points 123151

Jetez un coup d'œil à git bup qui est une extension de Git permettant de stocker intelligemment des binaires volumineux dans un dépôt Git.

Vous voudrez l'avoir en tant que sous-module, mais vous n'aurez pas à vous inquiéter que le dépôt devienne difficile à gérer. L'un de leurs exemples d'utilisation est le stockage d'images de machines virtuelles dans Git.

Je n'ai pas vraiment constaté de meilleurs taux de compression, mais mes dépôts ne contiennent pas de binaires vraiment volumineux.

Votre kilométrage peut varier.

3 votes

Bup fournit du stockage (en utilisant en interne des archives de parité pour la redondance et git pour la compression, la déduplication et l'historique), mais il n'étend pas git. git-annex est une extension de git qui fournit un backend de stockage bup .

0 votes

@Tobu quand j'ai posté ceci, git annex n'existait pas encore (dans les versions courantes)

2 votes

Bup est définitivement intéressant pour la gestion des gros fichiers. Je voulais souligner une différence dans l'interface utilisateur : vous utilisez les commandes bup en dehors de tout contexte de dépôt, et git est un détail d'implémentation.

28voto

C.. Points 10739

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

git fat init
git fat push
git fat pull

En outre, vous devez enregistrer un fichier .gitfat dans votre dépôt et modifier votre fichier .gitattributes afin de spécifier les extensions de fichier que vous souhaitez. git fat à gérer.

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

Enfin, il présente l'avantage que l'emplacement où sont stockés vos binaires peut être partagé entre les dépôts et les utilisateurs et qu'il prend en charge tout ce qui est nécessaire. rsync fait.

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

26voto

Daniel Fanjul Points 2375

J'utiliserais des submodules (comme Pat Notz) ou deux dépôts distincts. Si vous modifiez vos fichiers binaires trop souvent, alors j'essaierais de minimiser l'impact de l'énorme dépôt qui nettoie l'historique :

J'ai eu un problème très similaire il y a plusieurs mois : ~21 GB de fichiers MP3, non classés (mauvais noms, mauvais id3's, je ne sais pas si j'aime ce fichier MP3 ou pas...), 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é sur chaque ordinateur. Ensuite, j'ai commencé à les classer de la manière habituelle (en poussant, tirant, fusionnant... en supprimant et renommant 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 un nouveau commit, sans ancêtres de commit, et a démarré une nouvelle branche pointant vers ce commit. Le "git log" de cette branche ne montre qu'un seul commit.

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

Vous pourriez "purger" l'énorme dépôt de temps en temps de la même manière : Vos "clones git" seront plus rapides.

0 votes

J'ai fait quelque chose de similaire une fois où j'ai dû diviser un dépôt que j'avais fusionné accidentellement en deux dépôts distincts. Un modèle d'utilisation intéressant cependant :)

1 votes

Est-ce que ce serait la même chose que : rm -f .git ; git init ; git add . ; git commit -m "Trash l'historique."

1 votes

Oui, c'est la même chose seulement dans mon cas mp3. Mais parfois vous ne voulez pas toucher à vos branches et tags (pas de réduction d'espace dans les dépôts publics) mais vous voulez accélérer un "git clone/fetch/pull" d'une seule branche (moins d'espace pour les dépôts dédiés à cette branche).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X