对文本文件的GitHub 100MB文件大小限制有什么好的解决方法吗?

时间:2016-01-11 14:21:09

标签: git github large-files pre-commit-hook post-commit-hook

我有一个190 MB的纯文本文件,我想在github上跟踪。

文本文件是我们的文本转语音引擎的代词词典文件。我们经常在文本文件中添加和修改行,并且差异相当小,因此在这个意义上它对git来说是完美的。

但是,GitHub有一个严格的100 MB文件大小限制。我已经尝试过GitHub大文件存储服务,但是每次更改时都会上传整个190 MB文件的新版本 - 因此,如果我沿着这条路走下去,那么很快就会增长到几千兆字节。

我想将文件保留为一个文件,而不是将其拆分,因为这是我们的工作流程当前的状态,并且需要一些编码才能允许多个文本文件作为输入/输出在我们的工具中(我们没有太多的开发资源)。

我有一个想法是,是否可以设置一些预提交和提交后挂钩来自动拆分和连接大文件?那可能吗?

其他想法?

编辑:我知道StackOverflow上类似问题中描述的100 MB文件大小限制,但我不认为我的问题是重复的,因为我问对于差异很小且频繁的特定情况(我没有尝试上传大型ZIP文件或任何东西)。但是,我的理解是git-lfs仅适用于很少更改的文件,而普通的git非常适合我所描述的那种文件;除了GitHub有文件大小限制。

更新:我昨天花了一些时间尝试创建一个小型跨平台程序,该程序使用git hooks将文件拆分并连接成较小的文件。它有点工作但不太令人满意。您需要将.gitignore排除大文本文件,这使得git不知道它是否已更改。 git statusgit commit最初未检测到拆分文件,导致出现与此SO问题中描述的问题相同的问题,这非常令人讨厌:Pre-commit script creates mysqldump file, but "nothing to commit (working directory clean)"? 设置一个cron作业(linux)和计划任务(windows)以定期自动重新生成拆分文件可能会解决这个问题,但它不容易自动设置,可能会导致用户计算机出现性能问题,而且只是不是很优雅的解决方案。可能还需要一些像动态修改.gitignore这样的hacky解决方案,并且绝不会得到实际文本文件的差异,只有分割文件(尽管这可能是可接受的,因为它们非常相似)。

所以,睡着了,今天我觉得git hook方法毕竟不是一个好选择,因为它有太多的怪癖。正如@PyRulez所建议的那样,我认为我必须看看除GitHub之外的其他服务(不幸的是,因为我喜欢github)。托管解决方案更可取,以避免必须管理我们自己的服务器。我也希望它能公开上市......

更新2 :我已经查看了GitHub的一些替代方案,目前我倾向于使用GitLab。我已经联系GitHub支持有关提高100MB限制的可能性,但如果他们不能做到这一点,我将只为这个特定项目切换到GitLab。

3 个答案:

答案 0 :(得分:9)

清洁和涂抹

您可以使用干净和涂抹来压缩文件。通常情况下,这不是必需的,因为git会在内部压缩它,但由于gitHub表现得很奇怪,它可能有所帮助。主要命令如下:

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

GitHub会将此视为压缩文件,但在每台计算机上,它看起来都是一个文本文件。

有关详细信息,请参阅https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes

或者,您可以使用干净的帖子到在线pastebin,并从pastebin中获取污迹,例如http://pastebin.com/。许多其他组合都可以清洁和涂抹。

答案 1 :(得分:5)

一个非常好的解决方案是使用:

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

它是一个设计用于处理大文件的开源。

答案 2 :(得分:2)

您可以使用任何语言创建脚本/程序来分割或联合文件。

这里有一个分割用Java编写的文件的例子(我使用Java因为我觉得Java比其他任何人都更舒服,但是其他任何一个都可以工作,有些也会比Java更好)。

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);
    }
}

这几乎不需要任何费用(时间/金钱)。

编辑:您可以创建一个Java可执行文件并将其添加到您的存储库中,或者更简单,创建一个Python(或任何其他语言)脚本来执行此操作,并将其另存为纯文本你的存储库。