93 votes

Git peut-il traiter les fichiers ZIP comme des répertoires et les fichiers à l'intérieur du ZIP comme des blobs ?

Le scénario

Imaginez que je sois obligé de travailler avec certains de mes fichiers toujours stockés à l'intérieur. .zip fichiers. Certains des fichiers contenus dans le fichier ZIP sont de petits fichiers texte et changent souvent, tandis que d'autres sont plus volumineux mais heureusement plutôt statiques (par exemple, des images).

Si je veux placer ces fichiers ZIP à l'intérieur d'un dépôt Git, chaque ZIP est traité comme un blob, donc à chaque fois que je fais un commit, le dépôt augmente de la taille du fichier ZIP... même si seulement un petit fichier texte à l'intérieur a changé !

Pourquoi c'est réaliste

Microsoft Word 2007 / 2010 .docx et Excel .xlsx sont des fichiers ZIP...

Ce que je veux

Existe-t-il, par hasard, un moyen d'indiquer à Git de ne pas traiter les fichiers ZIP comme des fichiers, mais plutôt comme des répertoires et de traiter leur contenu comme des fichiers ?

Les avantages

Mais ça ne pourrait pas marcher, dites-vous ?

Je me rends compte que sans métadonnées supplémentaires, cela conduirait à une certaine ambiguïté : sur un fichier git checkout Git devrait décider s'il faut créer foo.zip/bar.txt comme un fichier dans un répertoire ordinaire ou un fichier ZIP. Cependant, cela pourrait être résolu par des options de configuration, je pense.

Deux idées sur la façon dont cela pourrait être fait (s'il n'existe pas encore)

  • en utilisant une bibliothèque telle que minizip o IO::Compress::Zip dans Git
  • ajouter d'une manière ou d'une autre une couche de système de fichiers de sorte que Git voit réellement les fichiers ZIP comme des répertoires au départ

2 votes

Le scénario avec .docx a du sens, mais dans de nombreux autres cas, vous pourriez envisager de suivre les fichiers individuels normalement avec git et seulement bâtiment le résultat .zip en utilisant un outil de construction approprié comme make .

2 votes

Si l'on considère que deux fichiers zip qui semblent différents l'un de l'autre peuvent contenir exactement les mêmes données (par exemple un fichier texte zippé deux fois avec deux niveaux de compression différents), cela devient beaucoup plus délicat. S'il est facile de représenter la différence entre les deux versions des fichiers décompressés avec peu d'informations, je suppose que représenter la différence entre les deux versions de l'archive (ce qui est essentiellement ce que git doit faire) avec à peu près aussi peu d'informations serait non trivial.

0 votes

Avez-vous jamais abouti à une solution mise en œuvre de Réponse de Jeff ou autre chose ? Je me demande à peu près la même chose, sauf que pour les archives tar ce qui devrait donner une réponse compatible...

29voto

Jeff Ferland Points 9485

Cela n'existe pas, mais cela pourrait facilement exister dans le cadre actuel. De la même manière que Git agit différemment avec l'affichage des fichiers binaires ou ASCII lorsqu'il effectue un diff, on pourrait lui demander d'offrir un traitement spécial à certains types de fichiers via l'interface de configuration.

Si vous ne voulez pas changer le code de base (bien que ce soit une idée assez cool), vous pouvez aussi script pour vous-même en utilisant crochets pré-commit et post-checkout pour décompresser et stocker les fichiers, puis les ramener à leur état .zip lors du paiement. Vous devrez restreindre les actions aux seuls fichiers blobs / index spécifiés par la fonction git add .

Dans les deux cas, cela représente un peu de travail - il s'agit juste de savoir si les autres commandes Git sont conscientes de ce qui se passe et jouent le jeu.

0 votes

Les hooks semblent être une bonne direction à suivre ; j'y ai pensé brièvement mais je n'étais pas sûr que cela puisse fonctionner. Le hook pre-commit peut modifier à la fois le système de fichiers et la zone de transit ?

2 votes

@Jonas Avez-vous réussi à faire cela et y a-t-il une chance que vous postiez une solution qui fonctionne ? J'aimerais suivre utilement les modifications apportées aux feuilles de calcul dans git et CSV n'est tout simplement pas adapté à nos besoins.

0 votes

Notez qu'en utilisant des scripts qui décompresseraient les fichiers archivés avant de les commettre dans le référentiel et les compresseraient à nouveau lors du checkout, un commit immédiatement suivi d'un checkout serait susceptible de modifier les archives, même si les fichiers stockés à l'intérieur de l'archive seraient inchangés.

19voto

Sippey Points 21

Zippey - Une solution utilisant Filtre pour les fichiers Git

Ma solution consiste à utiliser un filtre pour "aplatir" le fichier ZIP en un fichier texte monolithique et étendu (qui peut être énorme). Au cours de git add / commit le fichier ZIP sera automatiquement étendu à ce format de texte pour la diffusion normale du texte, et lors du passage à la caisse, il est automatiquement zippé à nouveau.

Le fichier texte est composé d'enregistrements, chacun représentant un fichier dans le fichier ZIP. On peut donc penser que ce fichier texte est une image textuelle du fichier ZIP original. Si le fichier dans le fichier ZIP est effectivement du texte, il est copié dans le fichier texte ; sinon, il est encodé Base64 avant d'être copié dans le fichier au format texte. Ainsi, le fichier texte reste toujours un fichier texte.

Bien que ce filtre ne fasse pas de chaque fichier du fichier ZIP un blob, les fichiers texte sont mappés ligne à ligne - ce qui est l'unité du diff - tandis que les changements des fichiers binaires peuvent être représentés par des mises à jour de leur Base64 correspondant. Je pense que cela est équivalent à ce que le PO imagine.

Pour plus de détails et un code de prototypage, vous pouvez lire le lien suivant :

Filtre de fichiers Git Zippey

Je tiens également à remercier l'endroit qui m'a inspiré cette solution : Description du fonctionnement du filtre à fichiers

0 votes

Ce filtre est encore en cours de développement, si vous avez des questions ou des suggestions, faites-le moi savoir.

1 votes

J'ai essayé ça et je pense que ça devrait bien marcher pour moi. J'ajouterais simplement quelque chose à la documentation indiquant que la liste de fichiers texte zippey.py doit être modifiée pour inclure tous les types de fichiers que vous voulez que zippey.py reconnaisse comme des fichiers texte.

1 votes

Des fichiers aussi volumineux ne sont pas compatibles avec de nombreux outils. Je pense notamment à la limite de 50 Mo imposée par Github.

18voto

VonC Points 414372

Utilice bup (présenté en détail dans GitMinutes #24 )

Il s'agit du seul système de type git conçu pour gérer des fichiers volumineux (voire très volumineux). muy grands), ce qui signifie que chaque version d'un fichier zip n'augmentera le repo que de son delta (au lieu d'une copie supplémentaire complète)

Le résultat est un repo git réel, qu'une commande Git normale peut lire.

Je détaille comment bup diffère de Git par " git avec de gros fichiers ".


Toute autre solution de contournement (comme git-annex ) n'est pas entièrement satisfaisant, comme l'explique en détail le document " git-annex avec des fichiers volumineux ".

1 votes

Le scénario était plutôt axé sur les fichiers XML tels que docx et xlsx (qui sont souvent assez petits) compressés. La taille du dépôt est plus petite avec bup, mais les changements réels dans le XML sont-ils visibles ?

0 votes

@Ruben c'est orienté vers les gros fichiers en taille ou en nombre. Mais il n'est pas très différent de git en terme de différence.

0 votes

Cela semble intéressant, mais pouvez-vous l'utiliser avec votre repo git actuel ?

10voto

De Gestion des formats de fichiers basés sur le format ZIP dans git :

(Note : selon le commentaire de Ruben (il ne s'agit que d'obtenir un diff correct, et non de livrer des fichiers décompressés).

Ouvrez votre fichier ~/.gitconfig (créez le s'il n'existe pas déjà) et ajoutez la stanza suivante :

[diff "zip"] textconv = unzip -c -a

Ce qu'il fait est d'utiliser "unzip -c -a FILENAME" pour convertir votre fichier zip en texte ASCII (unzip -c dézippe vers STDOUT). La prochaine étape est de créer/modifier le fichier REPOSITORY/.gitattributes et ajouter ce qui suit

*.pptx diff=zip

qui indique à git d'utiliser la description du zip-diffing de la configuration pour les fichiers les fichiers qui correspondent au masque donné (dans ce cas, tout ce qui se termine par .pptx). Maintenant, git diff décompresse automatiquement les fichiers et différencie la sortie ASCII. ASCII, ce qui est un peu mieux que "les fichiers binaires diffèrent". D'un autre côté, à cause du désordre alambiqué qu'est le XML correspondant des fichiers pptx, il n'est pas possible d'obtenir une différence. correspondant aux fichiers pptx, cela n'aide pas beaucoup, mais pour les fichiers ZIP incluant du texte (comme par exemple les archives de code source), cela peut être utile. incluant du texte (comme par exemple les archives de code source), c'est en fait assez pratique.

9voto

hoijui Points 960

ReZipDoc similaire à Zippey par sippey permet de manipuler les fichiers ZIP d'une manière plus agréable avec Git.

Comment cela fonctionne

Lors de l'ajout/commissionnement d'un fichier basé sur un ZIP, Rezip le décompresse et le reconditionne sans compression, avant de l'ajouter à l'index/commissionnement. Dans un fichier ZIP non compressé, les fichiers archivés apparaissent en l'état dans son contenu (ainsi que quelques méta-informations binaires avant chaque fichier). Si ces fichiers archivés sont des fichiers en texte brut, cette méthode fonctionnera très bien avec Git.

Avantages

Le principal avantage de Rezip par rapport à Zippey est que le fichier réel stocké dans le référentiel est toujours un fichier ZIP. Ainsi, dans de nombreux cas, il fonctionnera toujours en l'état avec l'application respective (par exemple Open Office), même s'il est obtenu sans passer par un filtre de re-packing-with-compression.

Mode d'emploi

Installez le(s) filtre(s) sur votre système :

mkdir -p ~/bin
cd ~/bin

# Download the filer executable
wget https://github.com/costerwi/rezip/blob/master/Rezip.class

# Install the add/commit filter
git config --global --replace-all filter.rezip.clean "java -cp ~/bin Rezip --store"

# (optionally) Install the checkout filter
    git config --global --add filter.rezip.smudge "java -cp ~/bin Rezip"

Utilisez le filtre dans votre référentiel, en ajoutant des lignes comme celles-ci dans le fichier <repo-root>/.gitattributes fichier :

[attr]textual     diff merge text
[attr]rezip       filter=rezip textual

# Microsoft Office
*.docx  rezip
*.xlsx  rezip
*.pptx  rezip
# OpenOffice
*.odt   rezip
*.ods   rezip
*.odp   rezip
# Misc
*.mcdx  rezip
*.slx   rezip

El textual c'est pour que ces fichiers soient réellement affichés comme des fichiers texte dans les diffs.

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