如何从Git中的“fatal: Out of memory? mmap failed: Cannot allocate memory”错误中恢复?

13

首先,让我解释一下背景:

我需要将一个至关重要的Magento网店升级到新版本。为了确保升级后所有现有代码仍然能正常工作,并做出一些升级后的更改,我从整个Magento安装中(不包括明显的内容,如4.5GB的图像、./var目录等)创建了一个Git存储库,将其推送到origin并在开发服务器上克隆了它。创建了一个新分支,执行了升级、代码更改,将所有内容提交到开发分支并推送回origin。

现在是时候升级“真正”的商店了,也就是说,我需要将生产服务器上的主分支与开发分支合并。但是接下来的一切都出了问题:

git fetch - 可行

git branch 说:* master

git merge origin/dev 出现不可描述的错误(经过一些等待后才有输出):

fatal: Out of memory? mmap failed: Cannot allocate memory

对于 git checkout dev, git rebase master origin/dev 等也都有同样的问题。

在 stackoverflow 上查阅了现有的问题并尝试了几种建议,包括但不限于:

git gc

Counting objects: 48154, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (37152/37152), done.
fatal: Out of memory, malloc failed (tried to allocate 527338875 bytes)
error: failed to run repack

并且:

git repack -a -d --window-memory 10m --max-pack-size 20m

Counting objects: 48154, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (37152/37152), done.
fatal: Out of memory, malloc failed (tried to allocate 527338875 bytes)

除了之前的命令,我还尝试了这个(它非常相似)。 由于链接提到可能存在32位系统问题,因此最好提供涉及三个系统规格的详细信息:

  • 'dev' 服务器: x86_64 Gentoo 2.6.38-hardened-r6 // 4核 & 8GB RAM
  • 'origin' 服务器: x86_64 Gentoo 2.6.38-hardened-r6 // 2核 & 4GB RAM
  • 'live' 服务器: x86_64 Debian 4.3.2-1.1 2.6.35.5-pv1amd64 // (VPS) 2核 & 3GB RAM

有人知道我该如何恢复吗?在 'origin' 上重新打包有效吗?如果有效,我怎样才能说服生产服务器获取仓库的新副本? 非常感谢任何帮助!


1
有类似的问题,重打包保存我的代码库,谢谢! - Ast Derek
2个回答

14

你遇到的错误来自于代码库中的大文件。Git 正在尝试将整个文件内容放入内存,这导致了错误。

尝试升级 Git

上个月发布了 Git 1.7.6 版本,其发布说明中有以下内容:

使用 "git add" 添加大于 core.bigfilethreshold(默认为半个Gig)的文件将直接将其内容发送到 packfile,而无需同时在内存中保存其压缩表示形式和原始形式。

升级到 1.7.6 版本可能使您能够运行 git gc,甚至可以运行 git merge,但我无法验证,因为很难将代码库达到那种状态(条件必须非常合适)。

尝试删除问题文件

如果升级 Git 没有帮助,您可以尝试使用 git filter-branch 从代码库中删除大文件。在此之前,尝试使用 git cat-file -p <commit_sha1>:path/to/large/file >/path/to/backup/of/large/file 备份大文件。

您需要在配置良好的计算机上执行这些操作(具有大量内存)。

如果操作成功,请尝试重新克隆到其他计算机上(或直接使用 rsync 复制 .git 目录)。


太好了!我今晚安排在那台特定的服务器上工作,所以我会有机会尝试一下。我真的希望这能完成任务!到目前为止,谢谢你 :) - Rem.co
最终它成功了!升级git没有起作用,但是使用filter-branchgit gc、本地重新克隆并将精简的repo强制推送到origin和生产服务器上解决了问题(当然这只是简短的故事;))。我已经预料到这会奏效,但是太害怕损坏任何东西了...在你告诉我那个cat-file技巧之前,我就已经这么想了,这提供了一个很好的备份,让我可以在清理所有内容之前进行。谢谢! - Rem.co
很高兴你终于搞定了。只可惜花费了那么多功夫!希望Git开发人员能尽快找出如何支持大文件,这样其他人就不会遇到同样的问题了。 - Richard Hansen

1

我看到有几份报告称,在非空目录中执行“git init --bare”时会出现这种情况。

你是否在使用/处理一个不为空的“裸”/“服务器”存储库(即除了.git目录之外还有其他内容)?


不,这里并非如此。该仓库是在“live”上通过常规的“git init”、一些.gitignore操作和之后的“git add .”来初始化内容创建的。然后在“origin”上,在一个新建的目录上执行了“git init --bare”,在声明了远程起点之后,从“live”到“origin”执行了“git push origin master”。在“dev”上执行了常规的“git pull origin master”。之后,像往常一样,通过“origin”从“dev”回到“live”。据我所知/记得,这里没有什么猴子乱搞的事情。 - Rem.co

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接