Je recherche des avis sur la façon de gérer les gros fichiers binaires dont dépend mon code source (application web). Nous discutons actuellement de plusieurs alternatives:
- Copiez les fichiers binaires à la main.
- Pro: Pas sûr.
- Contre: Je suis fortement contre cela, car cela augmente la probabilité d'erreurs lors de la configuration d'un nouveau site / de la migration de l'ancien. Construit un autre obstacle à franchir.
- Gérez-les tous avec Git .
- Pro: Supprime la possibilité d'oublier de copier un fichier important
- Contre: gonfle le référentiel et diminue la flexibilité pour gérer la base de code et les extractions, les clones, etc. prendront un certain temps.
- Référentiels séparés.
- Pro: La vérification / le clonage du code source est plus rapide que jamais et les images sont correctement archivées dans leur propre référentiel.
- Contra: supprime la simplicité d'avoir le seul et unique référentiel 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 référentiels Git et les gère-t-il 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.
Réponses:
Si le programme ne fonctionne pas sans les fichiers, il semble que les diviser en un référentiel séparé est une mauvaise idée. Nous avons de grandes suites de tests que nous divisons en un référentiel séparé, mais ce sont vraiment des fichiers "auxiliaires".
Cependant, vous pourrez peut-être gérer les fichiers dans un référentiel séparé, puis les utiliser
git-submodule
pour les tirer dans votre projet de manière saine. Donc, vous auriez toujours l'historique complet de toutes vos sources mais, si je comprends bien, vous n'auriez qu'une seule révision pertinente de votre sous-module d'images. L'git-submodule
installation devrait vous aider à garder la bonne version du code en ligne avec la bonne version des images.Voici une bonne introduction aux sous-modules de Git Book.
la source
J'ai découvert git-annex récemment que je trouve génial. Il a été conçu pour gérer efficacement les gros fichiers. 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'arborescence 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:
Il existe de nombreuses commandes disponibles et une excellente documentation sur le site Web. Un paquet est disponible sur Debian .
la source
git annex
est également disponible sur Windows . Si quelqu'un l'a déjà testé dans Windows, j'aimerais connaître son expérience!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 ne pouvez stocker des métadonnées que dans le référentiel git et le gros fichier ailleurs.
la source
lfs-test-server
est déclaré non destiné à la production. En fait, je travaille sur le serveur de production LFS ( github.com/artemkin/git-lfs-server ). Il est en cours, mais déjà utilisable, et nous le testons en interne.Jetez un œil à git bup qui est une extension Git pour stocker intelligemment de gros binaires dans un référentiel Git.
Vous voudriez l'avoir comme sous-module, mais vous n'aurez pas à vous soucier de la difficulté du référentiel à gérer. L'un de leurs exemples d'utilisation est le stockage d'images VM dans Git.
Je n'ai pas réellement vu de meilleurs taux de compression, mais mes référentiels ne contiennent pas de binaires vraiment volumineux.
Votre kilométrage peut varier.
la source
Vous pouvez également utiliser du git-fat . J'aime que cela ne dépend que du stock Python et
rsync
. Il prend également en charge le flux de travail Git habituel, avec les commandes explicites suivantes:De plus, vous devez archiver un fichier .gitfat dans votre référentiel et modifier vos .gitattributes pour spécifier les extensions de fichier que vous souhaitez
git fat
gérer.Vous ajoutez un binaire en utilisant la normale
git add
, qui à son tour invoque engit fat
fonction de vos règles gitattributes.Enfin, il a 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 ce qui est
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 référentiel Subversion. Cependant, si vous utilisez un référentiel Git pur, cela fonctionne à merveille.
la source
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 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 référentiel 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
etgit-commit-tree
pour créer un nouveau commit, sans ancêtre de commit, et j'ai commencé une nouvelle branche pointant vers ce commit. Le "git log" pour cette branche n'a montré qu'un seul commit.Ensuite, j'ai supprimé l'ancienne branche, conservé uniquement la nouvelle branche, supprimé les journaux de référence et exécuté "git prune": après cela, mes dossiers .git ne pesaient que ~ 6 Go ...
Vous pouvez "purger" l'énorme dépôt de temps en temps de la même manière: vos "git clones" seront plus rapides.
la source
La solution que je voudrais proposer est basée sur des branches orphelines et un léger abus du mécanisme de tag, désormais appelé * Stockage binaire de tags orphelins (OTABS)
TL; DR 12-01-2017 Si vous pouvez utiliser le LFS de github ou un autre tiers, vous devriez certainement le faire. Si vous ne le pouvez pas, poursuivez votre lecture. Soyez averti, cette solution est un hack et doit être traitée comme telle.
Propriétés souhaitables d'OTABS
git pull
etgit fetch
, y comprisgit fetch --all
sont toujours efficaces en bande passante , c'est-à-dire que tous les gros fichiers binaires ne sont pas extraits de la télécommande par défaut.Propriétés indésirables d'OTABS
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'utilisergit clone -b master --single-branch <url>
plutôt quegit clone
. C'est parce que git clone par défaut clone littéralement le référentiel entier , y compris les choses sur lesquelles vous ne voudriez pas normalement gaspiller votre bande passante, comme les commits non référencés. Tiré du SO 4811434 .git fetch <remote> --tags
bande passante inefficace, mais pas nécessairement le stockage inefficace. Vous pouvez toujours conseiller à vos collègues de ne pas l'utiliser.git gc
astuce pour nettoyer votre référentiel de tous les fichiers dont vous ne voulez plus.Ajout des fichiers binaires
Avant de commencer, assurez-vous d'avoir validé toutes vos modifications, votre arborescence de travail est à jour et votre index ne contient aucune modification non validée. Ce pourrait être une bonne idée de pousser toutes vos succursales locales vers votre télécommande (github, etc.) au cas où une catastrophe se produirait.
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 root.git rm --cached * .gitignore
.rm -fr * .gitignore
. Le.git
répertoire interne restera intact, car le*
caractère générique ne le correspond pas.git fetch
colmatage de 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 tapergit fetch <remote> --tags
, mais lisez la suite pour une solution de contournement. Allez-y etgit tag 1.0.0bin
git push <remote> 1.0.0bin
.git branch -D binaryStuff
. Votre validation ne sera pas marquée pour la récupération de place, car une balise orpheline pointant dessus1.0.0bin
est suffisante pour la maintenir en vie.Extraire le fichier binaire
git checkout 1.0.0bin -- VeryBigBinary.exe
.1.0.0bin
téléchargé la balise orpheline , auquel cas vous devrez augit fetch <remote> 1.0.0bin
préalable.VeryBigBinary.exe
dans votre master.gitignore
, afin que personne dans votre équipe ne pollue accidentellement l'historique principal du projet avec le binaire.Suppression complète du fichier binaire
Si vous décidez de purger complètement VeryBigBinary.exe de votre référentiel local, de votre référentiel distant et des référentiels de vos collègues, vous pouvez simplement:
git push <remote> :refs/tags/1.0.0bin
git tag -l | xargs git tag -d && git fetch --tags
. Tiré de SO 1841341 avec une légère modification.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. Extrait de SO 1904860git clone -b master --single-branch <url>
remplacergit clone
.2.0.0bin
. Si vous craignez que vos collègues tapent,git fetch <remote> --tags
vous pouvez en fait le nommer à nouveau1.0.0bin
. Cela garantira que la prochaine fois qu'ils récupèrent toutes les balises, les anciennes1.0.0bin
ne seront pas référencées et marquées pour la récupération de place ultérieure (en utilisant l'étape 3). Lorsque vous essayez d'écraser une balise sur la télécommande, vous devez utiliser-f
comme ceci:git push -f <remote> <tagname>
Épilogue
OTABS ne touche pas votre maître ni aucune autre branche de code source / 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 comme un travail distinct. Ce script pourrait être utile.
Confirmé de fonctionner sur Windows avec git-bash.
C'est une bonne idée d'appliquer un ensemble de trics standard pour rendre le stockage des fichiers binaires plus efficace. L'exécution fréquente de
git gc
(sans aucun argument supplémentaire) permet à git d'optimiser le stockage sous-jacent de vos fichiers en utilisant des deltas binaires. Cependant, s'il est peu probable que vos fichiers restent similaires d'une validation à l'autre, vous pouvez désactiver complètement les deltas binaires. De plus, comme 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 souhaiterez peut-être écrire des parties d'OTABS pour permettre une utilisation plus rapide. En particulier, les étapes de script 2-3 de Suppression complète de fichiers binaires dans un
update
hook git pourraient donner une sémantique convaincante mais peut-être dangereuse à git fetch ("chercher et supprimer tout ce qui est obsolète").Vous voudrez peut-être ignorer l'étape 4 de la suppression complète des fichiers binaires pour conserver un historique complet de toutes les modifications binaires sur la télécommande au détriment du ballonnement du référentiel central. Les référentiels locaux resteront légers au fil du temps.
Dans le monde Java, il est possible de combiner cette solution avec
maven --offline
pour créer une version reproductible hors ligne stockée entièrement dans votre contrôle de version (c'est plus facile avec maven qu'avec gradle). Dans le monde de Golang, il est possible de s'appuyer sur cette solution pour gérer votre GOPATH au lieu dego get
. Dans le monde python, il est possible de combiner cela avec virtualenv pour produire un environnement de développement autonome sans compter sur les serveurs PyPi pour chaque build à partir de zéro.Si vos fichiers binaires changent très souvent, comme des objets de construction, il pourrait être une bonne idée de scénario une solution qui stocke 5 la plupart des versions récentes des artefacts dans les balises orphelines
monday_bin
,tuesday_bin
...,friday_bin
et aussi une étiquette d'orphelin pour chaque version1.7.8bin
2.0.0bin
, etc. Vous pouvez faire pivoterweekday_bin
et supprimer quotidiennement les anciens fichiers binaires. De cette façon, vous obtenez le meilleur des deux mondes: vous conservez tout l' historique de votre code source mais uniquement l' historique pertinent de vos dépendances binaires. Il est également très facile d'obtenir les fichiers binaires pour une balise donnée sans obtenir le code source entier avec tout son historique:git init && git remote add <name> <url> && git fetch <name> <tag>
devrait le faire pour vous.la source
git gc
" - a arrêté la lecture juste là. Pourquoi quelqu'un abandonnerait-il sa dernière ceinture de sécurité au profit d'un hack?git gc
n'est pas dangereux à exécuter. Tous vos commits suspendus seront conservés en toute sécurité sur le disque dur pendant au moins 30 jours par défaut: git-scm.com/docs/git-gcgit push <remote> 1.0.0bin
-remote: error: GH001: Large files detected. You may want to try Git Large File Storage
. Il semble que GitHub ne supporte plus cela? Le binaire en question avait une taille de 100 Mo.À mon avis, si vous êtes susceptible de modifier souvent ces gros fichiers, ou si vous avez l'intention de faire beaucoup de
git clone
ougit checkout
, alors vous devriez sérieusement envisager d'utiliser un autre référentiel Git (ou peut-être une autre façon d'accéder à ces fichiers).Mais si vous travaillez comme nous le faisons et si vos fichiers binaires ne sont pas souvent modifiés, le premier clone / extraction sera long, mais après cela, il devrait être aussi rapide que vous le souhaitez (compte tenu du fait que vos utilisateurs continuent d'utiliser le premier référentiel cloné, ils eu).
la source
SVN semble gérer les deltas binaires plus efficacement que Git.
J'ai dû choisir un système de version pour la documentation (fichiers JPEG, fichiers PDF et fichiers .odt). Je viens de tester l'ajout d'un fichier JPEG et sa rotation à 90 degrés quatre fois (pour vérifier l'efficacité des deltas binaires). Le référentiel de Git a augmenté de 400%. Le référentiel de SVN n'a augmenté que de 11%.
Il semble donc que SVN soit beaucoup plus efficace avec les fichiers binaires.
Mon choix est donc Git pour le code source et SVN pour les fichiers binaires comme la documentation.
la source
git gc
la taille totale du référentiel git a été réduite à 184 Ko. Ensuite, j'ai changé un seul pixel du blanc au noir et j'ai validé ce changement, la taille totale du référentiel git est passée à 388 Ko, et après unegit gc
taille du référentiel git total a été réduite à 184 Ko. Cela montre que git est assez bon pour compresser et trouver des deltas de fichiers binaires.git clone --filter
de Git 2.19 + clones peu profondsCette nouvelle option pourrait éventuellement devenir la solution finale au problème des fichiers binaires, si les développeurs Git et GitHub le rendent suffisamment convivial (ce qu'ils n'ont sans doute toujours pas atteint pour les sous-modules par exemple).
Il permet de récupérer uniquement les fichiers et répertoires que vous souhaitez pour le serveur et a été introduit avec une extension de protocole à distance.
Avec cela, nous pourrions d'abord faire un clone superficiel, puis automatiser les blobs à récupérer avec le système de build pour chaque type de build.
Il en existe déjà un
--filter=blob:limit<size>
qui permet de limiter la taille maximale des blobs à récupérer.J'ai fourni un exemple détaillé minimal de l'apparence de la fonctionnalité: Comment puis-je cloner un sous-répertoire uniquement d'un référentiel Git?
la source
Personnellement, j'ai rencontré des échecs de synchronisation avec Git avec certains de mes hôtes cloud une fois que mes données binaires d'applications Web ont dépassé la barre des 3 Go . J'avais envisagé BFT Repo Cleaner à l'époque, mais c'était comme un hack. Depuis lors, j'ai commencé à garder les fichiers en dehors de Git, au lieu d' utiliser des outils spécialement conçus comme Amazon S3 pour gérer les fichiers, la gestion des versions et la sauvegarde.
Oui. Les thèmes Hugo sont principalement gérés de cette façon. C'est un peu maladroit, mais ça fait le travail.
Ma suggestion est de choisir le bon outil pour le travail . Si c'est pour une entreprise et que vous gérez votre ligne de code sur GitHub, payez l'argent et utilisez Git-LFS. Sinon, vous pourriez explorer des options plus créatives telles que le stockage de fichiers crypté décentralisé à l' aide de la chaîne de blocs .
Les options supplémentaires à considérer incluent Minio et s3cmd .
la source
Jetez un oeil à camlistore . Ce n'est pas vraiment basé sur Git, mais je le trouve plus approprié pour ce que vous devez faire.
la source