Git拉取错误:无法创建临时SHA1文件名

39

我设置了一个小的git repo,唯一的目的是在几台机器上进行本地开发(工作、家庭、笔记本电脑)。因此,我只有一个分支,并在离开计算机时进行提交/推送,下次启动时进行拉取。一直运行良好,直到现在。现在,当我在我的“实时测试”机器上拉取时,我得到以下信息:

remote: Counting objects: 38, done.
remote: Compressiremote: ng objects: 100% (20/20), done.
remote: Total 20 (delta 17), reused 0 (delta 0)
error: unable to create temporary sha1 filename .git/objects/ed: File exists

fatal: failed to write object
fatal: unpack-objects failed

在网上搜索后,我找到了唯一可靠的答案:http://marc.info/?l=git&m=122720741928774&w=2,它基本上说明这是一个虚假的错误信息,不代表实际出现了什么问题。

接下来我该如何查找出错原因呢?

编辑:删除本地副本并重新克隆。

19个回答

34

在 "Re: Bug? git svn fetch: "unable to create temporary sha1 filename /home/andres/git/public/crystal.g" 中提到:

在重新打包仓库(repacking)之后,问题已经解决了。真的相当奇怪。

你尝试过重新打包吗?

git-repack 用于将当前不在“包”中的所有对象组合成一个包。它还可以用于重新组织现有的包为单个更有效的包。
包是一组个别压缩并应用增量压缩的对象,存储在一个文件中,并带有关联的索引文件。
包用于减轻镜像系统、备份引擎、磁盘存储等的负载。

你尝试升级到最新版本的Git了吗?

为了“清理”你的仓库,你 需要运行不同的命令,从最安全的到最激进的:

$ git-prune
$ git-gc --aggressive
$ git-repack
$ git-repack -a
$ git-prune-packed

如 "Git垃圾回收似乎不能完全工作" 中所述,单独执行 git gc --aggressive 是不够的。
最有效的组合是添加 git repack,还有 git prune
git gc
git repack -Ad      # kills in-pack garbage
git prune           # kills loose garbage

提醒自己:不要忘记远程分支:https://dev59.com/amgu5IYBdhLWcg3wing4 - VonC
git repack -a刚才把我的存储库大小翻了一倍 T^T .. 谢天谢地,运行git gc之后恢复了之前的大小。 - Mazyod

33

就我个人而言,当我遇到这个问题时——在提交时——我尝试过 git-repackgit-gc,但都没有起作用。我得到了一个权限被拒绝的错误,于是我使用 chown 命令将整个存储库递归地更改为我预期的用户,然后就可以无问题地进行提交/推送/拉取。


1
这是一个有趣的变化 - 我曾经使用git-daemon管理我的一个代码库,但后来为了测试一些钩子而切换到本地提交/检出,因为git-daemon不会显示钩子stdio,并且git-daemon是以root权限运行的,而本地提交则归我所有。因此出现了问题。 - feoh

15

在多个用户提交到同一仓库时,我曾经遇到过这个错误,结果由于ssh和umask的缘故导致了组写权限问题。

你可以在配置文件的[core]部分设置sharedrepository=true,使新文件保留g+w模式:

cd /my/shared/repo.git
git repo-config core.sharedRepository true

# (might also need to "chmod -R g+wX ." for each 
# user that owns files in .git/objects)

编辑:

这种方法仅适用于已存在的代码库。你可以在创建代码库时使用以下命令来完成一次正确的操作:git --bare init --shared


2
这对我很有帮助,只是我使用了 git config --global --add core.sharedRepository all,因为 repo-config 已经被弃用并在新的 git 版本中删除。这个问题最初是在我用不同的 Git 工具(一个是 GitBash,另一个是通过 Cygwin 安装的)对同一个 repo 进行操作后出现的。 - Peter

12

我们遇到了与用户1先前提交时相同的问题,因此对象/ed目录由用户1创建并拥有。由于用户1的默认权限不允许用户2写入,因此用户2无法提交。

Git会按需创建这些目录作为某种哈希桶,因此它们可能由具有不同umask的几个不同的人拥有不同的权限。

我们通过首先将所有目录的chgrp更改为由同一组拥有,然后将它们全部chmod为g+w,使它们成为组可写,最后正确设置每个人的umask,以使所有新创建的桶也可由组写入来解决此问题。

这是因为我们正在使用ssh:// URL从git中检出 - 我假设如果我们使用git网络协议,它不会发生,因为git守护进程将具有一致的文件所有权。


6
在我的情况下,当我尝试推送时出现了这个问题。
dieter@dieter-dellD620-arch sugarcrmclient [master] git push origin
Counting objects: 16, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (10/10), done.
Writing objects: 100% (12/12), 3.91 KiB, done.
Total 12 (delta 1), reused 11 (delta 1)
error: unable to create temporary sha1 filename ./objects/7a: File exists

fatal: failed to write object
error: unpack failed: unpacker exited with error code
To gitosis@tiktak.kangaroot.net:sugarcrmclient.git
 ! [remote rejected] master -> master (n/a (unpacker error))
 ! [remote rejected] web -> web (n/a (unpacker error))
error: failed to push some refs to 'gitosis@tiktak.kangaroot.net:sugarcrmclient.git'

这不是权限问题。在本地运行git gc、git gc --aggressive、git repack或git prune都没有帮助。请注意错误信息中的“解包器错误”,我认为这很关键,因为它意味着问题出现在另一侧。所以我去了(裸)仓库并在那里运行了git gc。然后我就能正常推送了。


感谢指出解包器错误。对我来说,这是另一侧的权限问题。 - ckrailo
我也遇到了这个问题。由于服务器内存不足,我无法在服务器上运行git gc。所以我不得不将repo复制到一台更大的机器上,在那里运行git gc,然后再将其复制回来。之后一切都正常工作了。 - Eric Johnson
这也让我开始思考了。我的问题是,在我推送到裸仓库时,我的用户没有拥有一些./object文件。 - Shane

5

在使用git push时我遇到了这个问题。

然后我运行了git gc,它起作用了。

来自git-gc(1)手册页面:

git-gc - 清理不必要的文件并优化本地仓库。


1
只是想提醒一下,我尝试了一些方法,包括对整个存储库进行chown操作,但只有运行git gc才能解决我的问题。谢谢Wen。 - Mauvis Ledford

4

我遇到了这个问题,感觉已经尝试了以上所有方法。我之前遇到过这种情况,是由于不同用户在推送到存储库时的权限问题,但在这种情况下,每个人都在同一用户下推送,并且为了保险起见,我已经将存储库中的所有内容 chowned 给正确的用户和组,并且对其进行了 u+w 和 g+w 的 chmod。但我仍然收到 error: unable to create temporary sha1 filename ./objects/9a 的错误提示。

我刚刚做了更多的调查,发现权限确实有些问题:在推送之前,在服务器上托管的裸库中,对象文件夹中的所有文件都设置了 -rw-rw-r-- 的权限,这是你所期望的。它们都属于同一用户和组。在推送失败后,我可以使用 bash 命令 find . -perm 444 | xargs ls -l 查找权限设置为 -r--r--r-- 的文件,并显示它们的位置。执行该命令会给出以下结果:

-r--r--r-- 1 ourusername ourgroupname    730 Nov  4 15:02 ./objects/46/346f550340bc0d3fec24ea42b25999161f8c7a
-r--r--r-- 1 ourusername ourgroupname    177 Nov  4 15:02 ./objects/4c/664ebbfad568de6101a52c01f5117654945d6d
-r--r--r-- 1 ourusername ourgroupname    730 Nov  4 14:36 ./objects/9e/3f572366da9fb319331dfd924ae35cf9fd00ae
-r--r--r-- 1 ourusername ourgroupname    175 Nov  4 14:36 ./objects/aa/f42d7ed706f1d2e4a0aa1c5eb184e17e917204

这些都是最近更改的文件(发布时是11月4日15:08)。因此,看起来Git正在更新/替换文件(给它们一个新的时间戳),在此过程中更改权限,然后抱怨权限。我对这里发生的事情完全感到困惑 :(


2
如果其他人遇到了这个错误,我在跨越Windows和Linux之间工作时遇到了这个错误。看起来,如果换行符格式被转换为Windows,则在某些情况下仍然可以提交,但是git然后会将其转换为Linux格式。
因此,如果换行符是唯一的更改,则我们现在有两个相同的提交。由于提交哈希是从提交文件数据生成的,并且每个提交具有相同的数据,因此它们具有相同的哈希值。至少在我的情况下,这就是“文件已存在”的含义。Git变得非常混乱。
我通过在本地和中央存储库上执行git reset --hard 来解决它。

2

我的问题是权限问题。

我进入了目录,然后执行了cp -R repo repo_copy命令。

然后一切都恢复正常了。

但当我试图删除repo时,遇到了权限被拒绝的问题,检查了权限后发现权限已被更改,导致我当前用户没有写入权限...


2

就我个人而言,当我执行git push origin master时遇到了这个问题。 对我来说解决方案是: 在我的服务器上,我使用root登录到包含我的存储库的目录中并递归执行以下操作:

chown -hR MyGitUser MyRepo

一切正常运作。

我只有一个git用户,其他人通过发布公钥连接ssh。如果您配置多个git用户,则需要为每个用户执行相同的操作。


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