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...

5voto

Sukombu Points 33

Voici mon approche :

  • Utilisation des filtres diff de Git pour remplacer les fichiers d'archive par un résumé du contenu

    git config filter.zip.clean "unzip -v %f | tail -n +4 | head -n -2 | awk '{ print \$7,\$8 }' | grep -vE /$ | LC_ALL=C sort -sfk 2,2"
    git config filter.zip.smudge "cat"
    git config filter.zip.required true
  • Utilisation d'un pré-commissionnement crochet pour extraire et ajouter le contenu de l'archive :

    #!/bin/sh
    #
    # Git archive extraction pre commit hook
    #
    # Created: 2021 by Vivien Richter <vivien-richter@outlook.de>
    # License: CC-BY-4.0
    # Version: 1.0.2
    
    # Configuration
    ARCHIVE_EXTENSIONS=$(cat .gitattributes | grep "zip" | tr -d [][:upper:] | cut -d " " -f1 | cut -d. -f2 | head -c -1 | tr "\n" "|")
    
    # Processing
    for STAGED_FILE in $(git diff --name-only --cached | grep -iE "\.($ARCHIVE_EXTENSIONS)$")
    do
        # Deletes the old archive content
        rm -rf ".$(basename $STAGED_FILE).content"
        # Extracts the archive content, if the archive itself is not removed
        if [ -f "$STAGED_FILE" ]; then
            unzip -o $STAGED_FILE -d "$(dirname $STAGED_FILE)/.$(basename $STAGED_FILE).content"
        fi
        # Adds extracted or deleted archive content to the stage
        git add "$(dirname $STAGED_FILE)/.$(basename $STAGED_FILE).content"
    done
  • Utilisation d'un après le passage à la caisse crochet pour emballer à nouveau les archives pour l'usage :

    #!/bin/sh
    #
    # Git archive packing post checkout hook
    #
    # Created: 2021 by Vivien Richter <vivien-richter@outlook.de>
    # License: CC-BY-4.0
    # Version: 1.0.0
    
    # Configuration
    ARCHIVE_EXTENSIONS=$(cat .gitattributes | grep "zip" | tr -d [][:upper:] | cut -d " " -f1 | cut -d. -f2 | head -c -1 | tr "\n" "|")
    
    # Processing
    for EXTRACTED_ARCHIVE in $(git ls-tree -dr --full-tree --name-only HEAD | grep -iE "\.($ARCHIVE_EXTENSIONS)\.content$")
    do
        # Gets filename
        FILENAME=$(dirname $EXTRACTED_ARCHIVE)/$(basename $EXTRACTED_ARCHIVE | cut -d. -f2- | awk -F '.content' '{ print $1 }')
        # Removes the dummy archive file
        rm $FILENAME
        # Jumps into the extracted archive
        cd $EXTRACTED_ARCHIVE
        # Creates the real archive file
        zip -r9 ../"$FILENAME" $(find . -type f)
        # Jumps back
        cd ..
    done
  • Appliquer le filtre à la .gitattributes fichier :

    # Macro for all file types that should be treated as ZIP archives.
    [attr]zip text filter=zip
    
    # Forces `LF` as line endings for text based files inside ZIP archives.
    **/*.content/** text=auto eol=lf
    
    # OpenDocument
    *.[oO][dD][tT] zip
    *.[oO][dD][sS] zip
    *.[oO][dD][gG] zip
    *.[oO][dD][pP] zip
    *.[oO][dD][mM] zip
    
    # Krita
    *.[kK][rR][aA] zip
    
    # VRoid Studio
    *.[vV][rR][oO][iI][dD] zip
    *.[fF][vV][pP] zip
  • Ajouter un traitement binaire à la .gitattributes fichier :

    # Macro for all binary files that should use Git LFS.
    [attr]bin -text filter=lfs diff=lfs merge=lfs lockable
    
    # Images
    *.[jJ][pP][gG] bin
    *.[jJ][pP][eE][gG] bin
    *.[pP][nN][gG] bin
    *.[aA][pP][nN][gG] bin
    *.[gG][iI][fF] bin
    *.[bB][mM][pP] bin
    *.[tT][gG][aA] bin
    *.[tT][iI][fF] bin
    *.[tT][iI][fF][fF] bin
    *.[sS][vV][gG][zZ] bin
  • Ajoutez des éléments à la .gitignore fichier :

    # Auto generated LFS hooks
    .githooks/pre-push
    
    # Temporary files
    *~
  • Une certaine configuration par :

    1. Installer Git LFS
    2. Préparez LFS en lançant la commande git lfs install une fois.
    3. Configurer le filtre Git.
    4. Installez les hooks en lançant la commande git config core.hooksPath .githooks .
    5. Appliquez le crochet de vérification une fois en lançant la commande .githooks/post-checkout .
    6. Appliquez le filtre une fois en lançant la commande git add -A .

Pour un exemple, voir ici : Traitement ZIP pour Git

Problèmes connus

2voto

Brad Points 61171

Je pense que tu vas devoir monter un fichier zip sur le système de fichiers. Je ne l'ai pas utilisé, mais pensez à FUSE :

http://code.google.com/p/fuse-zip/

Il existe également ZFS pour Windows et Linux :

http://users.telenet.be/tfautre/softdev/zfs/

0 votes

Si je comprends bien, fuse-zip pourrait faire une couche entre le système de fichiers et git, mais zfs devrait être construit. en git n'est-ce pas ? Dommage que je ne sois pas toujours sous Linux avec ce repo, sinon fuse-zip serait une idée vraiment sympa.

2voto

Philip Oakley Points 3825

Les applications rencontrent souvent des problèmes avec les fichiers pré-zippés car elles s'attendent à ce que la méthode de compression ZIP et l'ordre des fichiers soient ceux qu'elles ont choisis. Je crois que OpenOffice Les fichiers .odf ont ce problème.

Cela dit, si vous utilisez simplement n'importe quel vieux fichier ZIP comme méthode de conservation des données, vous devriez être en mesure de créer quelques alias simples qui dézippent et re-zipent lorsque cela est nécessaire. La toute dernière MSysGit (alias Git pour Windows) dispose désormais de zip et unzip du côté du code shell, de sorte que vous pouvez les utiliser dans des alias.

Le projet sur lequel je travaille actuellement utilise des fichiers ZIP comme principal contrôle de version/archive locale. J'essaie donc d'obtenir un ensemble d'alias utilisables pour aspirer ces centaines de fichiers ZIP dans Git (et les en ressortir ;-) afin que les collègues de travail soient satisfaits.

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