如何修复由于中断的git fetch导致的损坏的git仓库?

19

如果 git fetch 因为 Ctrl-C 或者连接问题等原因被中断,之后执行 git fetch 或者 git pull 命令会失败。

Translated text:

If git fetch is interrupted, for example by Ctrl-C or connectivity problems, then executing git fetch or git pull commands will fail.

user@computer:~/code/openttd-git$ git fetch
^C
user@computer:~/code/openttd-git$ git fetch
error: Unable to find 22d90742fc79a9011fb86ee03d8aeea66bc12657 under http://git.openttd.org/openttd/trunk.git
Cannot obtain needed object 22d90742fc79a9011fb86ee03d8aeea66bc12657
error: Fetch failed.
我认为这与代码库无关。使用git clone将此破损的本地代码库复制到新的本地代码库中并不能解决问题。到目前为止,我知道的唯一解决方案是将整个远程代码库(origin/master)克隆到新的本地代码库中。但是是否有更好(更快)的解决方案呢?
有一个Debian bug报告,最后一条消息是在2011年2月发布的。这是我遇到的同样的错误吗?还是已经有修复或任何解决方案或解决方法了?我的git版本是1.7.10。
7个回答

14

尝试使用以下命令:

git fsck
git gc

4
您的要求已经被记录下来,非常感谢。以下是您需要翻译的内容:告诉一下命令的作用,这样对其他人会更有帮助。回答很好。 - Pablo Jomer
1
我刚遇到了同样的问题,这些命令并不能解决它(正如下面的评论中提到的)。 - Jan Stolarek
1
这并没有解决问题。$ git fsck 输出:Checking object directories: 100% (256/256), done. Checking objects: 100% (161159/161159), done. 然后 $ git gc 输出:Counting objects: 157646, done. Delta compression using up to 8 threads. Compressing objects: 100% (24579/24579), done. Writing objects: 100% (157646/157646), done. Total 157646 (delta 133211), reused 157173 (delta 132738)。然后 $ git fetch 输出与上述相同,所以这并没有解决问题。 - nrz
你可能需要在自己的代码库和从中获取的代码库中都运行这些命令。也许有一天我会确定真正重要的步骤,但我可以肯定地说,我的问题已经解决了。 - cdunn2001

7
在您的本地仓库中,在.git/objects/pack中找到一个*.pack.temp文件。然后找到一个与其同名的.idx文件,并将它们移开(或删除,但最好保险起见)。重新运行git fetch,它应该可以正常工作(对我来说是这样的)。
例如:
% git fetch
error: Unable to find a4fb0b54b2609df8a1ee4b97c268d205fc5bf9f1 under https://www.example.com/~someuser/something.git
Cannot obtain needed object a4fb0b54b2609df8a1ee4b97c268d205fc5bf9f1
error: fetch failed.

% ls -l .git/objects/pack
total 65872
-rw-r--r-- 1 someuser someuser    64072 Feb 12  2014 pack-2e31e66e67d8596f1193bbbc06c87293900c6e45.idx
-rw-r--r-- 1 someuser someuser    16920 Jul 21  2013 pack-3d76e0bf6c67d71913efc0711d56f04c7f79b95d.idx
-rw-r--r-- 1 someuser someuser    62224 Feb 11  2014 pack-74107fa80989df6619479874d94b5f8ed010fd2f.idx
-rw-r--r-- 1 someuser someuser    96552 Oct 30 22:55 pack-bb75633331ea0e74d4d3cb29f7660e1ba00fb899.idx
-rw-r--r-- 1 someuser someuser    73228 Mar  6  2014 pack-de0c1bcf3550cd7a2fd0c5a981bc17d15f1144c0.idx
-r--r--r-- 1 someuser someuser   129144 Feb  2 18:57 pack-ffb25d036dea040923468e2de07023f9b497aeb7.idx
-r--r--r-- 1 someuser someuser 46413554 Feb  2 18:57 pack-ffb25d036dea040923468e2de07023f9b497aeb7.pack
-r--r--r-- 1 someuser someuser   129312 Feb  2 19:10 pack-ffbdfa2c676aaf392ea722cb68eaa87e45af092c.idx
-rw-r--r-- 1 someuser someuser 20450545 Feb  2 19:09 pack-ffbdfa2c676aaf392ea722cb68eaa87e45af092c.pack
-rw-r--r-- 1 someuser someuser   129312 Feb  2 18:36 pack-ffbdfa2c676aaf392ea722cb68eaa87e45af092c.idx
-rw-r--r-- 1 someuser someuser  9863168 Feb  2 18:37 pack-ffbdfa2c676aaf392ea722cb68eaa87e45af092c.pack.temp

% mv .git/objects/pack/pack-ffbdfa2c676aaf392ea722cb68eaa87e45af092c.idx /tmp/
% mv .git/objects/pack/pack-ffbdfa2c676aaf392ea722cb68eaa87e45af092c.pack.temp /tmp/
% git fetch
From https://www.example.com/~someuser/something
   3288ab9..a4fb0b5  master     -> origin/master

2
谢谢,这个方法可行。需要注意的是,可能会有多个*.pack.temp和相应的*.idx文件(我有3个)。我将它们全部移动到了一个单独的目录中,之后git fetchgit merge origin/master就可以正常工作了。 - nrz

1
man git-fsck

建议使用rsync:

任何损坏的对象都需要在备份或其他存档中查找(即,您可以将其删除并与其他网站进行rsync,希望其他人拥有您损坏的对象)。

rsync -av user@host:repo/.git ./.git

对我有用


0
清理工作应该更简单了,因为在 Git 2.30(2021 年第一季度)中:"git fetch"(man) 被杀死时可能会留下一个 pack-objects 进程,仍在计算以找到良好的压缩,浪费资源。这个问题已经得到了解决。

请查看提交309a402(2020年12月1日)由Jeff King (peff)完成。
(由Junio C Hamano -- gitster --提交f3a112a中合并,2020年12月3日)

upload-pack:在信号或退出时终止pack-objects助手

签名作者:Jeff King

我们生成一个外部的pack-objects进程来将对象实际发送到远程端。如果在此过程中,我们被信号杀死,那么pack-objects可能会继续运行。一旦它开始为pack生成输出,它就会发现写入upload-pack失败并自行退出。
但在此之前,它可能会执行重要任务,如遍历对象图、压缩增量等,这些都是无意义的。因此,让我们确保尽快杀掉它,以便知道调用方不会读取结果时立即杀掉它。
由于本质上具有竞争性,因此这里没有测试,但是在像linux.git这样的大型repo上,可以轻松重现以下情况:
  • 确保您没有打包位图(因为它们使枚举阶段快速执行)。对于linux.git,在我的机器上,整个图形遍历需要大约30秒左右。
  • 运行 "git clone --no-local -q . dst(man); "-q"很重要,因为如果pack-objects正在将进度写入upload-pack(以通过侧带通道复用到客户端),则它将很快注意到写入stderr的失败
  • 在另一个终端中终止客户端侧克隆进程(不要使用^C,因为它将向所有进程发送SIGINT信号)
  • 运行 "ps au | grep git" 或类似命令以观察upload-pack是否在5秒内死亡(它将发送一个保持活动消息,以注意到客户端已经离开)
  • 但是在遍历和增量压缩阶段,您仍将看到pack-objects消耗100%的CPU(和1GB + RAM)。一旦开始写入pack(当它注意到upload-pack已经离开时),它就会退出。
有了这个修补程序,pack-objects会在upload-pack退出后立即退出。

0
你能否运行:
git reset --hard <some prior commit>

理论上,如果您刚刚运行了git fetch,您应该能够:
git reset --hard HEAD

这应该会丢弃由中断的获取操作引起的更改,将您的存储库恢复到先前的状态。此时,您应该能够重新运行您的fetch操作。


我能够成功运行 git reset --hard HEAD~20(例如),而且没有任何问题,但是 git fetchgit pull 的问题仍然存在。我认为“需要的对象”应该以某种方式进行修复,但我不知道如何修复。 - nrz

-1

很有可能仓库已经损坏。在服务器上运行 git fsckgit gc 可能会解决这个问题。从另一个目录克隆并拉取将会给你提交记录。然后,git fetch 就可以工作了,因为它只更新引用而不必获取任何对象。


-2

你尝试过清理代码库吗?

git gc

请注意,上述命令还会清除reflog记录。


git gc 输出如下内容:user@computer:~/code/openttd-broken-git$ git gc Counting objects: 150683, done. Delta compression using up to 8 threads. Compressing objects: 100% (24232/24232), done. Writing objects: 100% (150683/150683), done. Total 150683 (delta 126184), reused 150626 (delta 126127) bad sha1 file: .git/objects/22/d90742fc79a9011fb86ee03d8aeea66bc12657.temp 之后 git fetch 输出:error: Unable to find ce35909568caea9116c69b0a9d0cf6810d6507a5 under http://git.openttd.org/openttd/trunk.git Cannot obtain needed blob ce35909568caea9116c69b0a9d0cf6810d6507a5 ... - nrz

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