【问题标题】:failed to lock refs/heads/master remote bare repo未能锁定 refs/heads/master 远程裸仓库
【发布时间】:2019-07-16 14:11:50
【问题描述】:

我的问题是指post 中描述的情况。简而言之,有一个远程裸仓库和一个非裸仓库。根据计划,很少有人(包括我)应该能够将他们的更改推送到裸仓库。 hooks/post-receive 文件可以将这些更改自动拉入服务器的非裸仓库中。这是文件的内容:

!/bin/sh
cd /data/11_prywatne/14_Pawel/repo_pawel_non_bare/deploy || exit
unset GIT_DIR
git pull origin master

`chmod g+rwx -R /data/11_prywatne/14_Pawel/repo_pawel_non_bare/deploy/ &> /dev/null`

当我是唯一一个推动和拉动非裸回购的人时,一切都很顺利。但是,一旦另一个人git push origin master 出现了一些问题。例如,在远程非裸仓库尝试git pull origin master 时(我知道没有必要,因为有hooks/post-receive)我收到了这个错误:

fatal: Couldn't find remote ref master
fatal: The remote end hung up unexpectedly

我尝试用git log(在远程非裸机处)检查提交的历史是什么,并得到了这个错误:

error: Could not read <hash of the commit made by the other person>
fatal: Failed to traverse parents of commit 68e6227f4c4f84843ed7dd4fc03a159

git status(在远程非裸机处)返回以下输出:

# On branch master
error: Could not read <hash of the commit made by the other person>
error: Could not read <hash of the commit made by the other person>
fatal: Failed to traverse parents of commit 68e6227f4c4f84843ed7dd4fc03a15967051a97f

git push origin master(在远程非裸机处)返回:

error: Could not read <hash of the commit made by the other person>
fatal: Failed to traverse parents of commit 68e6227f4c4f84843ed7dd4fc03a15967051a97f
error: pack-objects died with strange error

(仍然在远程非裸)然后我决定git reset --hard,一切看起来都很正常,但git push origin master让我明白了:

error: unable to resolve reference refs/heads/master: Permission denied
remote: error: failed to lock refs/heads/master
To /data/11_prywatne/14_Pawel/gole.git/
 ! [remote rejected] master -> master (failed to lock)
error: failed to push some refs to '/data/11_prywatne/14_Pawel/gole.git/'
[user@server deploy]$ git pull origin master
fatal: git upload-pack: cannot find object <hash of the commit made by the other person>:
fatal: The remote end hung up unexpectedly

我切换到本地仓库并尝试推送。我遇到了同样的错误,表明问题是由Permission denied 引起的。我要求其他人为位于裸仓库refs/heads/master 中的文件设置组权限。问题貌似解决了,但是在尝试git push origin master时又出现了一个问题:

error: Ref refs/heads/master is at <hash of the commit made by the other person> but expected 0000000000000000000000000000000000000000
remote: error: failed to lock refs/heads/master
To server_ip:/data/11_prywatne/14_Pawel/gole.git/
 ! [remote rejected] master -> master (failed to lock)
error: failed to push some refs to 'user@server_ip:/data/11_prywatne/14_Pawel/gole.git/'

在尝试 git pull origin master 时,我得到:

fatal: git upload-pack: cannot find object <hash of the commit made by the other person>:
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

只是为了澄清。这是我本地机器上.git/config的内容:

[core]
        repositoryformatversion = 0
        filemode = false
        bare = false
        logallrefupdates = true
        symlinks = false
        ignorecase = true
[remote "origin"]
        url = user@server_ip:/data/11_prywatne/14_Pawel/gole.git/
        fetch = +refs/heads/*:refs/remotes/origin/*

其他人机器上的.git/config文件不同之处仅在于它指向的url (user2@server:/data/11_prywatne/14_Pawel/gole.git/)。

同一个文件,但在服务器的非裸仓库中:

[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        fetch = +refs/heads/*:refs/remotes/origin/*
        url = /data/11_prywatne/14_Pawel/gole.git/
[branch "master"]
        remote = origin
        merge = refs/heads/master

可能我在创建非裸仓库时错过了一些步骤。我应该考虑一些能够创建共享非裸仓库的内部 git 选项吗?我使用chmod 是否表明我犯了一个错误?我该如何解决这个问题?

【问题讨论】:

    标签: git permission-denied git-remote git-bare


    【解决方案1】:

    这是文件系统权限的问题,可能是因为推送到裸存储库的人使用不同的系统帐户这样做。您必须记住挂钩脚本在同一帐户下运行。如果裸仓库和非裸仓库中的任何权限 都太有限,那么在用户 B 也推送后,用户 A 将无法完全完成此操作 - 一些文件和内部 Git子目录将归 A 所有,部分归 B。

    因此,使用--shared 选项初始化两个存储库至关重要。您也可以在事后对其进行配置,但是您必须手动修复所有已存在且容易出错的文件系统权限。从头开始重新创建非裸仓库可能更容易。

    但是,这仍然不够,因为--shared 只影响 Git 自己的元数据,而不影响工作树。由于无法实际签出文件,您的拉取仍然可能失败。每次拉取操作创建新目录时,对它们的权限可能会过于严格。

    解决这个问题超出了 Git 的范围 - 您可能需要研究一下:

    • 让所有用户在该计算机上更改其帐户中的默认 umask;
    • 为所有这些用户设置一个共同的主要用户组(并不总是可行)或
    • 使用 POSIX ACL(诚然,这可能会让人很困惑)。

    如果您想回避这些问题,另一种选择是在频繁运行的 cronjob 中更新非裸 repo,这样您就可以确保它每次都由同一个用户运行。

    【讨论】:

    • 感谢您的评论。它阐明了我的下一步应该是什么。是否可以在post-receive 文件中实现其中一种解决方案?我相信所有从裸仓库推/拉的用户都在同一个组中。
    • @balkon16 如果与非裸仓库的所有交互都是通过 post-receive 挂钩发生的,那么是的,像 chmod -f -R g+w .; chgrp -f -R &lt;common group&gt; . (在拉取之后)可以工作。如果所讨论的组是所有用户的主要组,则第二部分是可选的。还要记住,这只有在 post-receive 钩子是用户与非裸仓库交互的唯一方式时才有效。
    猜你喜欢
    • 2012-06-29
    • 2011-06-20
    • 2018-12-25
    • 1970-01-01
    • 2015-11-20
    • 2019-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多