【问题标题】:What does git mean by, "unable to migrate objects to permanent storage"?git 是什么意思,“无法将对象迁移到永久存储”?
【发布时间】:2017-07-02 01:33:30
【问题描述】:

git 所说的“无法将对象迁移到永久存储”是什么意思?

 Counting objects: 4, done.
 Delta compression using up to 8 threads.
 Compressing objects: 100% (4/4), done.
 Writing objects: 100% (4/4), 956 bytes | 0 bytes/s, done.
 Total 4 (delta 2), reused 0 (delta 0)
 error: failed to push some refs to 'https://git.patrikx3.tk/server-scripts.git'
 To https://git.patrikx3.tk/server-scripts.git
 !  refs/heads/master:refs/heads/master [remote rejected] (unable to migrate objects to permanent storage)
 Done

【问题讨论】:

  • 谢谢,这是一个许可。
  • 您选择了正确的答案。我在下面的帖子中缺少什么?

标签: git git-push


【解决方案1】:

您可以看到 2016 年 10 月在 Git 2.11 的 commit 722ff7f 中引入的错误消息“unable to migrate objects to permanent storage”。

解释是:

receive-pack:隔离对象直到pre-receive 接受

当客户向我们推送对象时,index-pack 会检查对象本身,然后将它们安装到位。
如果我们因为pre-receive 钩子而拒绝推送,我们不能只删除包文件;其他过程可能取决于它。此时我们必须通过git gc 进行正常的可达性检查。

但由于gc.pruneExpire 宽限期,此类对象可能会存在数周。更糟糕的是,在此期间,它们可能会从包装中爆炸成低效的松散物体。

相反,此补丁教导 receive-pack 将新对象放入“隔离”临时目录。
我们使这些对象可用于连接检查和pre-receive 挂钩,然后仅在成功时将它们安装到位(否则将它们作为临时文件删除)。

代码是:

    /*
     * Now we'll start writing out refs, which means the objects need
     * to be in their final positions so that other processes can see them.
     */
    if (tmp_objdir_migrate(tmp_objdir) < 0) {
        for (cmd = commands; cmd; cmd = cmd->next) {
            if (!cmd->error_string)
                cmd->error_string = "unable to migrate objects to permanent storage";
        }
        return;
    }
tmp_objdir = NULL;

tmp_objdir_migrate() 函数来自 commit 2564d99(仍然适用于 Git 2.11)

它帮助调用者在对象目录中创建一个临时目录,以及一个可以传递给子程序以要求他们在那里写入的临时环境(原始对象目录仍然可以作为临时目录的替代访问)。

如前所述,这可能是由权限问题(或磁盘空间问题)引起的

此外,使用(在服务器端)git 2.10 可能会使该错误消失。


Git 2.13(2017 年第二季度)将扩展该隔离概念:
请参阅Jeff King (peff)commit d8f4481commit eaeed07commit 360244a(2017 年 4 月 10 日)。
(由 Junio C Hamano -- gitster -- 合并到 commit 9f1384f,2017 年 4 月 24 日)

git receive-pack man page 现在包括:

隔离环境

receive-pack 接收对象时,它们会被放入一个临时的 $GIT_DIR/objects 目录中的“隔离”目录和 仅在 pre-receive 钩子之后迁移到主对象存储 已完成。如果在此之前推送失败,则临时目录为 完全删除。

这有一些用户可见的效果和警告:

  1. 由于传入包的问题而失败的推送,丢失 对象,或者由于 pre-receive 钩子不会留下任何 磁盘上的数据。这通常有助于防止重复失败 从填满你的磁盘推动,但可以使调试更多 具有挑战性。

  2. pre-receive 钩子创建的任何对象都将在 隔离目录(仅在成功后才迁移)。

  3. pre-receive 挂钩不得更新任何指向的引用 隔离对象。访问存储库的其他程序将 无法看到对象(如果 pre-receive 挂钩失败, 那些 refs 会被损坏)。


razor7the comments求婚:

在我的例子中,使用 Docker 的 GitLab,从主机服务器(不是 GitLAb 容器)运行这些命令

cd /media/data/gitlab/data/git-data/repositories/@hashed 
grep "gitlab-user/repo-name" . -R 
cd /media/data/gitlab/data/git-data/repositories/@hashed/found-folder 
chown -R 998:998 ./hash-repo-folder-name.git/. 

请记住,998 可能因您而异。

【讨论】:

  • 权限!以前做我们存储库的人有一个总是使用 root 的习惯。 chmod -R g+w *,修正错误。
  • chmod -R g+w * 修复我的问题
  • chown -R git:giton the objects 文件夹(gitlab 服务器:存储库)修复了这个问题。一些objects 文件夹神秘地归root 所有(实际上是2 个)。
  • 我也有同样的情况,但是每次推送新文件时似乎都是使用错误的权限创建的 - 有没有办法决定使用哪些权限创建它们?
  • @razor7 感谢您的反馈。我已将您的评论包含在答案中以提高知名度。
【解决方案2】:

据推测,当它压缩对象时,它会将它们暂时放在某个地方,然后在一个单独的动作中尝试将它们移动到它们的永久位置。移动它们意味着将它们从临时位置复制到永久位置,然后将它们从临时位置删除,或者让它们由其他处理删除,可能在另一个时间。例如,在 Linux 中写入/tmp 目录的许多文件和目录通常会保留在那里,直到操作系统在下次重新启动时将它们删除(如果曾经重新启动的话)。

失败看起来像是缺少写入远程位置的权限。当 git 尝试将其压缩的对象移动到您将在项目配置中指定的远程位置 https://git.patrikx3.tk/server-scripts.git 时发生故障。不太可能,您可以在命令中或(我认为?)在全局配置中指定它。

【讨论】:

    猜你喜欢
    • 2019-02-04
    • 2020-06-18
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    • 2014-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多