【问题标题】:git is very very slow when tracking large binary filesgit 在跟踪大型二进制文件时非常慢
【发布时间】:2011-03-04 14:04:48
【问题描述】:

我的项目已经六个月了,git 非常非常慢。我们跟踪大约 30 个大小为 5 MB 到 50 MB 的文件。这些是二进制文件,我们将它们保存在 git 中。我相信这些文件让 git 变慢了。

有没有办法从存储库中杀死所有大小 > 5MB 的文件。我知道我会丢失所有这些文件,这对我来说没问题。

理想情况下,我想要一个列出所有大文件 (> 5MB) 的命令。我可以看到列表,然后我说好吧,继续删除那些文件,让 git 更快。

我应该提到 git 不仅在我的机器上很慢,而且在暂存环境中部署应用程序现在需要大约 3 个小时。

所以修复应该会影响服务器,而不仅仅是存储库的用户。

【问题讨论】:

  • 你可以尝试使用来自git-bigfiles项目的git
  • 你可能想尝试使用 git-annex 之类的东西来管理二进制文件。 git-annex.branchable.com
  • 如果它对任何人有用,让我补充一点,我的 Cygwin 版本的 git 挂在变基上。当我使用 Git-Bash 时,同一个存储库没有问题。
  • 不知道现在是不是这样。我希望他们对压缩效果低于 50%(或任何其他可选择的 X%)的所有内容都关闭压缩。在某些时候,速度显然超过了硬件空间!

标签: git


【解决方案1】:

你会收集垃圾吗?

git gc

这会显着提高速度,即使对于小型存储库也是如此。

【讨论】:

  • 当杂物过多时会自动完成。我怀疑它真的会帮助 OP。
  • @Jefromi,这是新的吗?我昨天刚升级到1.7.1,但在此之前我使用的版本肯定没有自动运行gc
  • @kubi: 嗯,它并没有永远存在,但它并不是全新的——它从 caf9de2(2007 年 9 月 14 日)开始从 commit、merge、am 和 rebase 中调用,或者稳定版本 v1.5.4(2008 年 2 月 1 日)。
  • 再想一想,git gc 不可能在 commitmerge 上调用,否则 git fsck --unreachable 将永远不会返回任何内容。
  • 找到了。自动gc 运行之前的默认松散对象数量为 6700,这解释了为什么我从未见过它运行。
【解决方案2】:

说明

Git 非常擅长处理小文本文件的大量历史记录,因为它可以有效地存储它们及其更改。同时,git 非常不擅长二进制文件,并且会天真地存储文件的单独副本(by default, at least)。正如您所观察到的,存储库变得庞大,然后变得缓慢。

这是 DVCS 中的一个常见问题,每次克隆时都会下载每个文件的每个版本(“整个存储库”),这一事实加剧了这一问题。 Kiln 的人正在开发一个插件,以将这些大文件更像 Subversion,它只按需下载历史版本。

解决方案

这个命令会列出当前目录下所有大小>= 5MB的文件。

find . -size +5000000c 2>/dev/null -exec ls -l {} \;

如果您想从存储库的整个历史记录中删除文件,您可以将此想法与git filter-branch 一起使用来遍历历史记录并消除所有大文件的痕迹。完成此操作后,存储库的所有新克隆都将变得更精简。如果您想在不克隆的情况下精简存储库,您可以在 man page 上找到说明(请参阅“缩小存储库的清单”)。

git filter-branch --index-filter \
    'find . -size +5000000c 2>/dev/null -exec git rm --cached --ignore-unmatch {} \;'

警告:这将使您的存储库与其他克隆不兼容,因为树和索引签入了不同的文件;你将无法再推或拉它们。

【讨论】:

  • 注意:这是 Unix/Linux 版本的 find,而不是 Windows find.exe。
  • +1。可能想先将find 的输出发送到文件,检查列表,然后使用git rm,以防万一有任何错误命中。或者,在删除大文件后检查git status,并使用git checkout HEAD <file> 找回任何错误删除的文件。
  • 我认为您对 git“默认存储单独的副本”的评论是倒退的。根据您默认链接到 (thread.gmane.org/gmane.comp.version-control.git/146957/…) 的电子邮件链, git 尝试 来区分二进制文件——这就是导致问题的原因;不是存储空间。
【解决方案3】:

这是一个经过审查的修订版,旨在减少负面和煽动性:

当涉及到不是逐行文本文件的文件时,Git 有一个众所周知的弱点。目前没有解决方案,核心 git 团队也没有宣布解决此问题的计划。如果您的项目很小,例如 100 MB 左右,则有一些解决方法。 git 项目存在一些分支来解决这个可扩展性问题,但这些分支目前还不成熟。其他一些修订控制系统没有这个特定问题。在决定是否选择 git 作为您的修订控制系统时,您应该将此问题视为众多因素之一。

【讨论】:

  • “Git 有一个众所周知的弱点......” - 需要引用
  • 我知道。谁需要报价时其实际常识。只是不要将 git 用于二进制文件。使用 perforce 或专门的资产管理。
  • @v.oddou 嗯,“我知道”和“它的实际常识”是有区别的。这件事是不是每个人都知道它,可能它甚至不完全正确。因此,任何类型的引用都可以改善这个答案。没关系,但肯定不是杰出的和备份的。
  • 好吧,不是火上浇油,但如果你在谷歌上搜索“git 和二进制文件缓慢”,就会发现很多链接报告用户在管理二进制文件时遇到问题git 中的文件。此外,使用一个或另一个 SCM 的开发人员知道每个系统的优缺点......因此,当二进制文件被放入存储库时,git 已经形成了非常缓慢的声誉。
  • 在我使用过的所有介绍性资源中,git 对二进制文件都不好。存在 git-annex 来解决这个问题。 git 很棒,但不适用于二进制数据。最好链接到添加二进制功能的分叉,这样人们就可以支持这项工作。
【解决方案4】:

对于二进制文件和 git 处理它们的方式没有什么特别的。当您将文件添加到 git 存储库时,会添加一个标头并使用 zlib 压缩该文件并在 SHA1 哈希后重命名。无论文件类型如何,这都是完全相同的。 zlib 压缩中没有任何东西对二进制文件造成问题。

但在某些时候(推送、gc)Git 开始考虑增量压缩内容的可能性。如果 git 找到相似的文件(文件名等),它会将它们放在 RAM 中并开始将它们压缩在一起。如果您有 100 个文件,并且每个文件都说 50Mb,它会尝试同时将 5GB 放入内存中。为此,您必须添加更多内容才能使事情正常进行。您的计算机可能没有这么多 RAM,它开始交换。这个过程需要时间。

您可以限制 delta 压缩的深度,以便进程不使用那么多内存,但结果是压缩效率较低。 (core.bigFileThreshold、delta 属性、pack.window、pack.depth、pack.windowMemory 等)

所以有很多想法可以让 git 很好地处理大文件。

【讨论】:

  • 请参阅here,了解如何禁止这些“增量”尝试发生。
【解决方案5】:

加快速度的一种方法是使用--depth 1 标志。有关详细信息,请参见手册页。我不是一个伟大的 git 大师,但我相信这相当于 p4 getsvn get,也就是说它只给你最新的文件而不是“给我所有文件的所有修订通过无时无刻不在”,这就是 git clone 所做的。

【讨论】:

  • 这不允许你从存储库推送,所以它的用处有限。
【解决方案6】:

你告诉 git 那些文件是二进制的吗?

例如将*.ext binary 添加到您的存储库的.gitattributes

【讨论】:

  • 我假设告诉 git 文件是二进制文件会加快速度。
  • 如果 git 的启发式算法无法自动判断文件是二进制文件,则可能。
【解决方案7】:

您还可以将 BFG Repo Cleaner 视为清理大文件的更快更简单的方法。

https://rtyley.github.io/bfg-repo-cleaner/

【讨论】:

    【解决方案8】:

    自 2008 年以来,我一直在 Windows 和 GNU/linux 上运行 Git,我跟踪的大多数文件都是二进制文件。我的一些存储库有几个 GB,包含 Jpeg 和其他媒体。 我在家里和工作中都有很多运行 Git 的计算机。

    我从未有过原帖描述的症状。但就在几周前,我在一台旧的 Win-XP 笔记本电脑上安装了 MsysGit,几乎无论我做什么,它都让 git 停止运行。即使只用两三个小文本文件进行测试也慢得离谱。我们正在谈论 10 分钟来添加一个小于 1k 的文件......似乎 git 进程永远保持活力。在这台计算机上,其他一切都按预期工作。
    我从最新版本降级到 1.6,问题就消失了...
    我有其他相同品牌的笔记本电脑,也有由同一 IT 部门安装的 Win-XP 形成相同的图像,无论版本如何,Git 都可以正常工作...... 所以那台特定的计算机一定有什么奇怪的地方。

    我还对二进制文件和压缩进行了一些测试。如果你有一张 BMP 图片,你对它做了一些小改动并提交它们, git gc 会很好地压缩。 所以我的结论是压缩不取决于文件是否是二进制文件。

    【讨论】:

      【解决方案9】:

      只需将文件设置为被忽略即可。请参阅以下链接:

      http://help.github.com/git-ignore/

      【讨论】:

      • @Jefromi 实际上,如果您查看我发布的链接,您会发现第二段中有说明告诉他在这种情况下该怎么做。
      • 是的。但是您回答的直接内容是“忽略文件”,而不是“从跟踪中删除文件然后忽略它们”。写在这里通常比链接到另一个网站要好。
      【解决方案10】:

      那是因为 git 不可扩展。

      这是 git 中的一个严重限制,被 git advocacy 淹没了。搜索 git 邮件列表,您会发现数百名用户想知道为什么只有区区 100 MB 的图像(例如,对于网站或应用程序)会使 git 崩溃。问题似乎是几乎所有的 git 都依赖于他们称之为“打包”的优化。不幸的是,除了最小的文本文件(即源代码)之外,打包效率低下。更糟糕的是,随着历史的增加,它的效率越来越低。

      这确实是git中一个令人尴尬的缺陷,被吹捧为“快速”(尽管缺乏证据),git开发人员对此心知肚明。他们为什么不修呢?您会在 git 邮件列表中找到来自 git 开发人员的回复,他们无法识别问题,因为他们的 Photoshop 文档 (*.psd) 是专有格式。是的,真的很糟糕。

      结果如下:

      将 git 用于您不想为其设置单独存储库的小型、仅源代码项目。或者对于您希望利用 git 的去中心化开发的复制整个存储库模型的小型源代码项目。或者当您只是想学习一种新工具时。所有这些都是使用 git 的好理由,而且学习新工具总是很有趣。

      如果您有大型代码库、二进制文件、庞大的历史记录等,请不要使用 git。我们的存储库中只有一个是 TB。 Git无法处理它。 VSS、CVS 和 SVN 处理得很好。 (不过,SVN 膨胀了。)

      另外,给 git 时间成熟。它仍然不成熟,但它有很大的动力。随着时间的推移,我认为 Linus 的实用性将克服 OSS 纯粹主义者,而 git 最终将在更大的领域中使用。

      【讨论】:

      • 这个答案确实过于消极和煽动性。是的,git 存在二进制文件的可伸缩性问题。对于代码来说,它的可扩展性和速度都非常快。有很多速度的证据(尽管您的断言相反),甚至忽略 CVS/SVN 需要网络访问而不是磁盘访问来进行许多操作这一事实。有很多历史悠久的大型项目都非常乐意使用 git。
      • 还有……你对 Photoshop 的东西有兴趣吗?我不会浪费时间写详细的回复,但是如果通过阅读整个线程thread.gmane.org/gmane.comp.version-control.git/146957/…(也许您因为线程中的约翰是您而生气?),我会看到很多关于如何进行的合理回复最好用当前的 git 处理这个问题,将来如何解决,以及为什么这不是他们的首要任务。
      • 是的,我不认为你是对的,在这里。对于 Linux 内核来说,Git 的方式工作得非常好,不值得被轻视,“不可扩展”。
      • 这条评论如果有链接或数据来支持它会更可信。顺便说一句,你觉得 mercurial 怎么样?
      • 也许他没有表达流行的观点,但我认为他的反对票在“消极”方面比 OP 的回答更过分。我们应该鼓励不同意见,而不是仅仅因为有人不喜欢今年的版本控制风格而大肆宣扬。 GIT 确实不太适合跟踪二进制文件。但它非常适合源代码,这是主要意图,这就是它在 linux 内核中表现出色的原因。
      猜你喜欢
      • 2011-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-02
      • 1970-01-01
      • 2015-01-08
      • 1970-01-01
      相关资源
      最近更新 更多