web-dev-qa-db-fra.com

Existe-t-il de bonnes solutions de contournement à la limite de taille de fichier GitHub 100 Mo pour les fichiers texte?

J'ai un fichier texte brut de 190 Mo que je veux suivre sur github.

Le fichier texte est un fichier Lexicon de prononciation pour notre moteur de synthèse vocale. Nous ajoutons et modifions régulièrement des lignes dans les fichiers texte, et les différences sont assez petites, donc c'est parfait pour git dans ce sens.

Cependant, GitHub a une limite de taille de fichier stricte de 100 Mo en place. J'ai essayé le service de stockage de fichiers volumineux GitHub, mais qui télécharge une nouvelle version de l'intégralité du fichier de 190 Mo à chaque fois qu'il change - de sorte que cela augmenterait rapidement en plusieurs gigaoctets si je suivais ce chemin.

Je voudrais conserver le fichier sous la forme un fichier au lieu de le fractionner car c'est ainsi que fonctionne actuellement notre flux de travail et il faudrait un certain codage pour autoriser plusieurs fichiers texte en entrée/sortie dans nos outils (et nous n'avons pas beaucoup de ressources de développement).

Une idée que j'ai eue est qu'il est peut-être possible de configurer des hooks avant et après validation pour diviser et concaténer automatiquement le gros fichier? Cela serait-il possible?

D'autres idées?

Edit : Je suis conscient de la limitation de taille de fichier de 100 Mo décrite dans les questions similaires ici sur StackOverflow, mais je ne considère pas que ma question est un doublon car Je demande le cas spécifique où les différences sont petites et fréquentes (je n'essaie pas de télécharger un gros fichier Zip ou quoi que ce soit). Cependant, ma compréhension est que git-lfs ne convient qu'aux fichiers qui rarement changent, et que git normal conviendrait parfaitement au type de fichier que je décris; sauf que GitHub a une restriction de taille de fichier.

Mise à jour : J'ai passé hier à expérimenter avec la création d'un petit programme multiplateforme qui divise et joint des fichiers en fichiers plus petits en utilisant des crochets git. Ça marche mais pas vraiment satisfaisant. Vous devrez faire exclure votre gros fichier texte par .gitignore, ce qui rend git ignorant s'il a changé ou non. Les fichiers divisés ne sont pas initialement détectés par git status ou git commit et conduit au même problème que celui décrit dans cette SO, ce qui est assez ennuyeux: le script de pré-validation crée le fichier mysqldump, mais "rien à valider (répertoire de travail propre ) "? La configuration d'un travail cron (linux) et d'une tâche planifiée (windows) pour régénérer automatiquement les fichiers fractionnés régulièrement peut résoudre ce problème, mais il n'est pas facile à configurer automatiquement, peut entraîner des problèmes de performances sur l'ordinateur des utilisateurs, et n'est tout simplement pas une solution très élégante. Certaines solutions hacky comme la modification dynamique de .gitignore pourraient également être nécessaires, et en aucun cas vous n'obtiendrez un diff des fichiers texte réels, seulement les fichiers divisés (bien que cela puisse être acceptable car ils le seraient très similaire).

Donc, après avoir dormi dessus, je pense qu'aujourd'hui, l'approche git hook n'est pas une bonne option après tout car elle a trop de bizarreries. Comme l'a suggéré @PyRulez, je pense que je vais devoir regarder d'autres services que GitHub (malheureusement, puisque j'adore github). Une solution hébergée serait préférable pour éviter d'avoir à gérer notre propre serveur. J'aimerais aussi qu'il soit accessible au public ...

Mise à jour 2 : J'ai examiné quelques alternatives à GitHub et actuellement je penche pour l'utilisation de GitLab. J'ai contacté le support GitHub sur la possibilité d'augmenter la limite de 100 Mo, mais s'ils ne le font pas, je vais simplement passer à GitLab pour ce projet particulier.

20
josteinaj

Nettoyer et maculer

Vous pouvez utiliser Clean et Smudge pour compresser votre fichier. Normalement, cela n'est pas nécessaire, car git le compressera en interne, mais comme gitHub agit bizarrement, cela peut aider. Les commandes principales seraient les suivantes:

git config filter.compress.clean gzip
git config filter.compress.smudge gzip -d

GitHub le verra comme un fichier compressé, mais sur chaque ordinateur, il semblera être un fichier texte.

Voir https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes pour plus de détails.

Alternativement, vous pouvez avoir un message propre sur un Pastebin en ligne et tacher la récupération à partir du Pastebin, tel que http://Pastebin.com/ . De nombreuses autres combinaisons sont possibles avec un nettoyage et des taches.

10
PyRulez

Une très bonne solution sera d'utiliser:

https://git-lfs.github.com/

C'est une source ouverte conçue pour fonctionner avec des fichiers volumineux.

5
CodeWizard

Vous pouvez créer un script/programme dans n'importe quelle langue pour diviser ou unir des fichiers.

Voici un exemple pour diviser un fichier écrit en Java (J'ai utilisé Java parce que je me sens plus à l'aise sur Java que tout autre) autre, mais tout autre fonctionnerait, certains seront meilleurs que Java aussi).

public static void main(String[] args) throws Exception
{
    RandomAccessFile raf = new RandomAccessFile("test.csv", "r");
    long numSplits = 10; //from user input, extract it from args
    long sourceSize = raf.length();
    long bytesPerSplit = sourceSize/numSplits ;
    long remainingBytes = sourceSize % numSplits;

    int maxReadBufferSize = 8 * 1024; //8KB
    for(int destIx=1; destIx <= numSplits; destIx++) {
        BufferedOutputStream bw = new BufferedOutputStream(new FileOutputStream("split."+destIx));
        if(bytesPerSplit > maxReadBufferSize) {
            long numReads = bytesPerSplit/maxReadBufferSize;
            long numRemainingRead = bytesPerSplit % maxReadBufferSize;
            for(int i=0; i<numReads; i++) {
                readWrite(raf, bw, maxReadBufferSize);
            }
            if(numRemainingRead > 0) {
                readWrite(raf, bw, numRemainingRead);
            }
        }else {
            readWrite(raf, bw, bytesPerSplit);
        }
        bw.close();
    }
    if(remainingBytes > 0) {
        BufferedOutputStream bw = new BufferedOutputStream(new FileOutputStream("split."+(numSplits+1)));
        readWrite(raf, bw, remainingBytes);
        bw.close();
    }
        raf.close();
}

static void readWrite(RandomAccessFile raf, BufferedOutputStream bw, long numBytes) throws IOException {
    byte[] buf = new byte[(int) numBytes];
    int val = raf.read(buf);
    if(val != -1) {
        bw.write(buf);
    }
}

Cela ne coûtera presque rien (temps/argent).

Edit: Vous pouvez créer un Java exécutable et l'ajouter à votre référentiel, ou encore plus facile, créer un Python (Ou tout autre autre langue) pour ce faire, et enregistrez-le en texte brut sur votre référentiel.

2
Mayuso