为什么Git不能处理大文件和大型回购?

时间:2015-04-01 14:27:21

标签: git

SO和其他地方的数十个问题和答案强调Git无法处理大型文件或大型回购。建议使用一些变通方法,例如git-fatgit-annex,但理想情况下,Git会本地处理大型文件/存储库。

如果此限制已存在多年,是否有理由尚未取消限制?我认为Git中存在一些技术或设计挑战,这使得大文件和大型repo支持非常困难。

很多相关的问题,但似乎都没有解释为什么这是一个很大的障碍:

3 个答案:

答案 0 :(得分:14)

基本上,它取决于权衡。

你的一个问题有一个来自Linus本人的例子:

  

[...] CVS,即它真的最终面向“一次一个文件”模式。

     

哪个好,因为你可以拥有一百万个文件,然后只查看其中一些 - 你甚至都看不到其他999,995个文件的影响。

     从根本上说,Git从来没有真正看过不到整个回购。即使你稍微限制一些事情(即只检查一部分,或者让历史记录稍微退一步),git最终仍然关心整个事情,并传授知识。

     

如果你强迫它把所有东西看作一个巨大的存储库,那么git会非常糟糕。我不认为这部分是可以修复的,尽管我们可以改进它。

     

是的,那就是“大文件”问题。我真的不知道如何处理大文件。我知道,我们会嘲笑他们。

正如您将找不到具有O(1)索引访问和插入的数据结构一样,您将找不到能够完美地执行所有操作的内容跟踪器。

Git故意选择在某些方面做得更好,对别人不利。


磁盘使用情况

由于Git是DVCS(分布式版本控制系统),每个人都拥有整个仓库的副本(除非您使用相对较新的浅层克隆)。

这有一些真正优点,这就是为什么像Git这样的DVCS变得非常受欢迎。

然而,使用SVN或CVS的中央服务器上的4 TB回购是可管理的,而如果你使用Git,每个人都不会为携带它而感到激动。

Git有一个很好的机制,可以通过跨文件创建delta链(“diffs”)来最小化repo的大小。 Git在创建它们时不受路径或提交命令的限制,它们确实工作得很好....有点像对整个仓库进行压缩。

Git将所有这些小差异放入packfiles中。 Delta链和packfiles使得检索对象需要更长的时间,但这对于最小化磁盘使用非常有效。 (还有那些权衡。)

这种机制对于二进制文件不起作用,因为它们往往会有很大不同,即使在“小”更改之后也是如此。


<强>记录

当您签入文件时,您将永远拥有它。你的孙子孙女的孙子每次克隆你的回购时都会下载你的猫gif。

这当然不是git独有的,因为DCVS会使后果更加重要。

虽然可以删除文件,但git的基于内容的设计(每个对象id是其内容的SHA)使得删除这些文件变得困难,侵入性和破坏历史记录。相比之下,我可以从工件仓库或S3存储桶中删除crufty二进制文件,而不会影响我的其他内容。


<强>难度

使用非常大的文件需要很多仔细的工作,以确保最小化您的操作,并且永远不会将整个内容加载到内存中。在创建具有与git一样复杂的特征集的程序时,这非常难以可靠地完成。


<强>结论

最终,开发人员说“不要把大文件放在Git中”有点像那些说“不要把大文件放在数据库中”的人。他们不喜欢它,但任何替代方案都有缺点(在一种情况下Git整合,ACID合规和FK与另一种)。实际上,它通常可以正常工作,特别是如果你有足够的记忆。

它的效果不如它的设计效果好。

答案 1 :(得分:5)

git&#34;无法处理&#34;这是不对的。大文件。只是您可能不希望使用git来管理大型二进制文件的存储库,因为git repo包含每个文件的完整历史记录,而delta压缩是大多数类型的二进制文件比在文本文件上有效得多。结果是一个非常大的repo,需要很长时间才能克隆,使用大量磁盘空间,并且由于其必须通过大量数据,因此对于其他操作来说可能会慢得令人无法接受。

替代方案和附加组件(如git-annex)分别存储大型二进制文件的修订版,其方式违反了git通常的假设,即每个以前的存储库状态可以脱机使用在任何时候,但避免必须运送如此大量的数据。

答案 2 :(得分:0)

这是因为每个结帐都包含每个文件的每个版本。

现在,git有一些方法可以缓解这个问题,例如二进制差异和稀疏克隆,但是每个客户端肯定会在每个文件中至少有两个副本(一个在工作树中,一个在存储库中)。这是的问题取决于您的具体情况。