What does git mean by, “unable to migrate objects to permanent storage”?

之前偶尔发现提交代码会出现被拒绝情况,一开始以为可以用 gc 来解决问题,或者通过创建创建新分支或者重新提交代码来规避,然后发现被拒绝概率越来越高。遇到问题解决问题。

各种 google、百度加 stackOverflow,终于在 stackOverflow 上面看到一种解释,主要针对较高版本 git 和 gitlab,本地在提交 commit 的时候需要先提交到 tmp_objdir_migrate 然后再提交到仓库里面

    /*
     * 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;

Quarantine Environment

When receive-pack takes in objects, they are placed into a temporary “quarantine” directory within the $GIT_DIR/objects directory and migrated into the main object store only after the pre-receive hook has completed. If the push fails before then, the temporary directory is removed entirely.

This has a few user-visible effects and caveats:

  1. Pushes which fail due to problems with the incoming pack, missing objects, or due to the pre-receive hook will not leave any on-disk data. This is usually helpful to prevent repeated failed pushes from filling up your disk, but can make debugging more challenging.
  2. Any objects created by the pre-receive hook will be created in the quarantine directory (and migrated only if it succeeds).
  3. The pre-receive hook MUST NOT update any refs to point to quarantined objects. Other programs accessing the repository will not be able to see the objects (and if the pre-receive hook fails, those refs would become corrupted).

根据被拒绝的 log:./objects/c5/77e0eb9f2a855232d6b26e957ad71c431fdbaa: Permission denied 我们知道这个目录文件夹出问题了,于是我们想去找到服务器项目所在的路径,发现里面空空如也,一般项目路径下面会有 xx.git 代表这个仓库所在文件夹,然而没有,貌似只有 @hash 里面有很多不规则命名的文件夹。

一开始以为 git 文件夹被谁意外删掉了,然而 gitlab 网页加载正常,完全没有被删掉的异常表现。之前修复问题的时候弄坏过 git 项目,弄坏了的 git 项目,网页是会加载失败。

于是去看看 gitlab 相关知识,看了相关文档,原来项目路径都被放到 @hash 这个文件夹下面了,要查到项目具体路径,提供了两种方法,一种是通过 gitlab 网页客户端的 admin 后台,另外一种是通过 gitlab rail 命令行后台,通过

Project.find(16).disk_path // id 可以到项目设置里面看得到,不需要太高权限
Project.find_by_full_path('group/project').disk_path

都可以找到具体路径

修复

于是找到路径,查看项目的 c5 路径权限,权限果然不对,所有者居然是 root 不是 git,导致 git 写入失败,最终通过修改文件夹所有者改为 git 之后,提交成功

gitlab hash 文件夹文档:https://docs.gitlab.com/ee/administration/repository_storage_types.html
https://docs.gitlab.com/ee/user/admin_area/index.html#administering-projects
https://docs.gitlab.com/ee/administration/operations/rails_console.html#starting-a-rails-console-session

Linux 文件夹权限说明:
https://www.cnblogs.com/sxdcgaq8080/p/7498906.html

git push 失败 Stack Overflow 资料:
https://stackoverflow.com/questions/42214667/what-does-git-mean-by-unable-to-migrate-objects-to-permanent-storage
https://stackoverflow.com/questions/49627374/git-remote-rejected-unable-to-migrate-objects-to-permanent-storage

SourceTree + GitLab Enterprise Edition 项目导入

一、SourceTree 安装

直接在 SourceTree 官网 https://www.sourcetreeapp.com/ 下载安装适合自己系统的版本,之前 SourceTree 客户端不需要创建账号之类的,可以直接进行 git 地址 clone,最近版本需要进行账号登陆,如果没有账号创建一个,如果有账号,也可以用其他人的账号进行安装。

二、GitLab 配置

SourceTree 支持账号登陆,也支持最原始的 SSH Key 进行登陆,如果是公司内部搭建的而且是没有做过任何修改的企业版,如果要支持账号登陆就需要支持双重认证。

You can also use personal access tokens to authenticate against Git over HTTP. They are the only accepted password when you have Two-Factor Authentication (2FA) enabled.

如果没有开启双重认证就会提示你验证失败。于是只好选择 SSH Key 方式,通过自己生成 SSH Key 在默认用户录下

步骤1.检查是否已经存在SSH Key

打开电脑终端,输入以下命令:

ls -al ~/.ssh   

会出现两种情况  

步骤2. 生成/设置SSH Key

继续上一步可能出现的情况   

(1)情况一:终端出现文件id_rsa.pub 或 id_dsa.pub,则表示该电脑已经存在SSH Key,此时可继续输入命令:

这样你需要的SSH Key 就已经复制到粘贴板上了,然后进行步骤3

< ~/.ssh/id_rsa.pub  

(2)情况二:终端未出现id_rsa.pub 或 id_dsa.pub文件,表示该电脑还没有配置SSH Key,此时需要输入命令:

ssh-keygen -t rsa -C “your_email@example.com”  

选一般的常用的邮箱即可,不常用的邮箱一般不推荐)            

 默认会在相应路径下(/your_home_path)生成id_rsa和id_rsa.pub两个文件,此时终端会显示:

连续回车即可,也可能会让你输入密码,密码就是你的开机密码 

然后把公钥放在Gitlab 上面的个人设置 SSH Keys 选项中。

三、git 项目导入

因为 SourceTree 默认认为你有 git 命令支持,假如电脑里面没有 git 环境,是不能够通过 SourceTree 的 git 地址直接 clone 的,没有任何提示。

这个时候就需要用 Mac 或者 Windows 的命令终端去查看支不支持git 命令,Window 如果没有安装那就需要主动去安装 git,Mac 上面如果没有安装,使用 git 命令时会提示你安装,当然你也可以自己去官网下载安装,并且配置 git 路径。

安装好 git 之后,直接在 gitlab 项目里面拷贝 git 地址到 SourceTree 的通过 url clone 项目的选项,可以自定义项目路径,然后点击克隆即可。

四、git 项目提交测试

一般拉取权限很低不需要用到 SSH Key,提交权限需要用到 SSH Key。这个时候通过确定提交是否成功来查看 SSH Key 配置的正确。如果本地提交成功,可以通过 gitlab 网页查看操作是否成功,如果失败那就可能需要重新配置 SSH Key。