Git代码库重新打包失败。

69

我有一个存储在内存有限的服务器上的Git仓库。当我尝试从服务器克隆现有的仓库时,会出现以下错误:

hemi@ubuntu:$ git clone ssh://hemi@servername.dk/home/hemi/repos/articles
Initialized empty Git repository in /home/hemi/Skrivebord/articles/.git/
hemi@servername.dk's password: 
remote: Counting objects: 666, done.
remote: warning: suboptimal pack - out of memory
remote: fatal: Out of memory, malloc failed
error: git upload-pack: git-pack-objects died with error.
fatal: git upload-pack: aborting due to possible repository corruption on the remote side.
remote: aborting due to possible repository corruption on the remote side.
fatal: early EOF
fatal: index-pack failed
hemi@ubuntu:$ 
为了处理这个错误,我尝试重新打包原始存储库(根据这个论坛帖子)。但是它并没有描述如何重新打包存储库,而是描述了如何使用 "git pack-objects" 命令。
hemi@servername:~/repos/articles$ git repack -a -d --window-memory 10m --max-pack-size 100m
usage: git pack-objects [{ -q | --progress | --all-progress }]
        [--all-progress-implied]
        [--max-pack-size=N] [--local] [--incremental]
        [--window=N] [--window-memory=N] [--depth=N]
        [--no-reuse-delta] [--no-reuse-object] [--delta-base-offset]
        [--threads=N] [--non-empty] [--revs [--unpacked | --all]*]
        [--reflog] [--stdout | base-name] [--include-tag]
        [--keep-unreachable | --unpack-unreachable 
        [<ref-list | <object-list]

服务器上已安装 Git 1.6.5.7 版本。

9个回答

120

你的解决方案让你在本地和远程拥有了一个可用的副本,但是当远程仓库再次决定重新打包时,这将会再次引起问题。幸运的是,你可以设置配置选项,在两个存储库中减少需要重新打包的内存量--这些选项实际上是将你添加的命令行参数作为重新打包时的默认选项。因此,你应该登录到远程系统,切换到存储库并执行以下操作:

git config pack.windowMemory 10m
git config pack.packSizeLimit 20m
你可能希望在本地仓库上执行相同的操作。(顺便提一句,我猜你的仓库要么很大,要么这些机器内存很小-对我来说这些值似乎很低。)就我个人而言,在过去重新打包非常大的存储库时遇到malloc失败时,我还更改了core.packedgitwindowsizecore.packedgitlimitcore.deltacachesizepack.deltacachesizepack.windowpack.threads的值,但听起来你不需要进一步的选项 :)

2
谢谢提供配置选项,我之前不知道它们的存在。该代码库包含大量的PDF文件。代码库的总大小(包括.git目录和被追踪的文件)大约是1.1GB。所以我猜这是一个大型的代码库;-) - midtiby
@MarkLongair:您真是救了我的一天!我正准备跑去商店买些内存升级:D - Andresch Serj
在Dreamhost,我必须使用pack.windowMemory 10m、pack.packSizeLimit 20m、pack.deltacachesize = 20m、pack.threads = 2以及core.deltacachesize = 20m、core.packedgitlimit = 30m。感谢@MarkLongair。 - UrsoBranco

25

对于无法直接访问存储库且无法执行重新打包的情况,我通过执行浅克隆,然后逐步增加深度进行抓取来解决问题。

git clone YOUR_REPO --depth=1
git fetch --depth=10
...
git fetch --depth=100
git fetch --unshallow    //Downloads all history allowing to push from repo

希望它仍然可以帮助到某些人。


作为许多工作的最后一招,这实际上起作用了。谢谢。 - Sajib Acharya
1
git clone REPO --depth=1 still failed for me with the error remote: aborting due to possible repository corruption on the remote side. - Flimm
1
这是一种有点过时的方法,但它确实有用。我发现某些原因下,最大深度只能设为300... - Vinz

17

我使用以下步骤解决了这个问题。

  1. 从服务器到本地机器上检出仓库 (使用 ssh 的原始复制方式)
  2. 重新打包本地仓库
    git repack -a -d --window-memory 10m --max-pack-size 20m
  3. 在服务器上创建一个空的仓库
    git init --bare
  4. 将本地仓库推送到服务器上
  5. 检查是否能够克隆服务器仓库

6
很高兴听到您解决了那个问题,但我要提醒您,当服务器决定重新打包其存储库时,您将再次面临同样的问题。最好在远程存储库中设置配置选项(例如,如我的回答所建议的),这样当它自动重新打包时,您仍然不会因为内存不足而出现问题。 - Mark Longair

6

这并没有解答问题,但是有人可能遇到这个问题:当 pack-objects 被某种内存杀手(比如 Dreamhost 使用的 Killing Memory)终止时,重新打包也可能在服务器上失败:

$ git clone project-url project-folder
Cloning into project-folder...
remote: Counting objects: 6606, done.
remote: Compressing objects: 100% (2903/2903), done.
error: pack-objects died of signal 9284.51 MiB | 2.15 MiB/s   
error: git upload-pack: git-pack-objects died with error.
fatal: git upload-pack: aborting due to possible repository corruption on the remote side.
remote: aborting due to possible repository corruption on the remote side.
fatal: early EOF
fatal: index-pack failed

在Dreamhost上,这似乎是由 mmap 引起的。重新打包代码使用 mmap 将一些文件的内容映射到内存中,由于内存杀手不够智能,它会将mmapped文件计算为已使用的内存,当Git尝试 mmap 大文件时,就会杀死Git进程。
解决方法是编译一个自定义的Git二进制文件,并关闭 mmap 支持(configure NO_MMAP=1)。

你知道是否可以将NO_MMAP=1选项添加到现有的git安装中吗? - Max Williams
1
我不这么认为,它看起来像是一个预处理宏,导致产生不同的代码。但这只是我的观点,我没有进行研究。 - zoul

1

git config --global pack.window 0


1

我正在使用 git 版本 1.7.0.4,并且它接受此命令。可能 git 版本 1.6 不接受此命令。

尝试创建一个带有一些随机提交的新存储库。然后使用此命令重新打包它。


1
你是在说这个命令吗?git repack -a -d --window-memory 10m --max-pack-size 100m - Flimm

0

我在Ubuntu 14.10上遇到了同样的问题,使用git 2.1.0连接私有github.com存储库时出现了问题。(怀疑是企业路由器的问题!在不同的WiFi网络上可以正常使用,但在工作场所却无法连接)

* GnuTLS recv error (-54): Error in the pull function.
* Closing connection 2jects:  31% (183/589)   
error: RPC failed; result=56, HTTP code = 200
fatal: The remote end hung up unexpectedly
fatal: protocol error: bad pack header

我的解决方案是使用ssh进行git克隆(我事先设置了ssh密钥),如下所示:
git clone https://github.com/USERNAME/REPOSITORYNAME.git 变成了:
git clone git@github.com:USERNAME/REPOSITORYNAME.git
*:(生成ssh密钥)
ssh-keygen -t rsa -C“您在domain.com上注册的电子邮件地址”
然后登录github,在设置中导入ssh密钥,并从~/.ssh/id_rsa.pub导入它。

我听说企业路由器可以进行内容扫描并在HTTP连接中断,但从未听说过在HTTPS上这样做 - 您的路由器是否也会解码和重新加密HTTPS流量? - Rup
Rup:在连接到互联网之前,涉及到两个路由器。下周,我将检查该特定公司的设置情况。我已经验证了它在其他任何地方(任何其他WiFi网络)都没有出现故障,只是在那个特定的公司。 - arcol

0
在我的情况下,我收到了同样的错误信息,但问题出在 Github 方面。
经过大约一个小时的维护,他们修复了它,问题也得到了所有计算机的解决。

0
在我的情况下,更改这些配置值并没有帮助 - GIT 仍然会以稍微不同的错误崩溃。
有所帮助的是简单地重新启动服务器(在我的情况下,使用 sudo shutdown -r now 命令)。似乎是因为服务器上有某个进程占用了大量的内存,使得 GIT 无法分配内存。
希望对其他人也有所帮助。

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