【问题标题】:Git ! [remote rejected] master -> master (failed to lock)吉特! [远程拒绝] master -> master(锁定失败)
【发布时间】:2020-08-23 14:12:24
【问题描述】:

我无法推送到我的 git 存储库。 git clonegit pull 工作正常,但 git push 不起作用。

我检查了here 等其他答案,尝试了git push origin master --force 等几种方法。但错误仍然相同。

这是屏幕截图。

其他细节:

$ git show-ref refs/remotes/origin/master
8a205a0741f85fa309031a45f3613bf95a99148f refs/remotes/origin/master

$ git rev-parse --symbolic-full-name master
refs/heads/master

$ git rev-parse master
35ae39a241cd6bbfe7a9092f72b08279159e0056

$ git show-ref master
35ae39a241cd6bbfe7a9092f72b08279159e0056 refs/heads/master
8a205a0741f85fa309031a45f3613bf95a99148f refs/remotes/origin/master

请帮助我摆脱这个错误。

更新

$ git ls-remote
From https://xxx.git
8a205a0741f85fa309031a45f3613bf95a99148f        HEAD
8a205a0741f85fa309031a45f3613bf95a99148f        refs/heads/master
58feda6564bd52b9cce53da9862343aefd704202        refs/heads/new-0505
f24cd00e2f587689cdb92671769817c271bf0759        refs/heads/telestop
2a1afdf637a9108471eeddc755d49b74ef51e567        refs/meta/gitblit/reflog
8a205a0741f85fa309031a45f3613bf95a99148f        refs/remotes/origin/master

【问题讨论】:

  • 你能试试git push origin master:master吗?老实说,我无法解释为什么 - 我四处寻找你的错误,这是更常见的建议之一,但原因却大不相同,据我所知,你不属于这些。唯一的共同点是 Git 对分支和实际分支的了解存在一些错误。在一种情况下,它试图推送到大写错误的分支名称,另一种情况是推送到分支名称a/b,但已经有一个分支a。或者本地 git 索引中可能有垃圾。
  • @VLAZ 感谢您的指示。但是git push origin master:master 的输出与git push origin master 相同。
  • failed to lock 是您的 Git 报告从 other Git 转发的错误,并且至少在这种情况下无法锁定那里,不是由于您可以修复的任何问题从你的终点。您必须让有权访问服务器的人进入,看看有什么问题并在那里修复它。
  • 可能是权限问题,尽管细节部分取决于服务器运行的操作系统以及该操作系统的配置方式。 Windows 系统存在打开文件的问题;当您打开最严格的安全选项 (SELinux) 时,Linux 系统将无法使用。
  • @torek 你是对的。我已经从服务器检查了ref/heads,其中存在master.lock 文件。删除文件后,git push 成功。您能否发表您的推荐作为答案并解释创建锁定文件时可能出现的情况?

标签: git github gitblit


【解决方案1】:

这种失败有几个可能的原因。根据comment,这原来是服务器上挥之不去的master.lock 文件。手动删除就足够了。

因为失败的原因可能不止一个,所以只提供一个具体的答案并不是那么有用。但是,我们可以在这里概述一般过程,以及可能出现的问题。

请记住,分支和标签名称是 refsreferences 的特定形式。每一个都只持有一个哈希 ID。标记名称通常包含标记 object 或提交对象的哈希 ID,它创建一个带注释的标记,并且一旦创建,就永远不会更改。但是,分支名称标识了提交链中的一个提交,并且该提交被视为属于该分支的最后一个提交。 (可能会有后续提交,但它们不包含在该分支中。请注意,由分支名称标识的提交可以包含在 other 分支中。)这样做的结果是,随着分支的增长,这些值会定期更改。所以必须更新 配对。

这些名称-值对可能应该保存在某种事务数据库中,但不是。 Git 目前(截至今天的 2.26.2 版本的所有版本,并且可能会持续很长一段时间)将所有这些引用存储在两个位置中的一个或两个位置:一个名为 packed-refs 的单个平面文件,或存储的单个文件在文件系统中,例如refs/heads/master。要查找名称,Git 首先检查单个文件是否存在。如果是这样,该文件将具有正确的值。如果不存在,Git 会检查该名称是否存在于 packed-refs 文件中,如果存在,则使用那里的值。如果两个搜索都失败,则该名称不存在。

为了确保任何 update 都是原子的——当一个 Git 命令正在更新名称时,没有其他 Git 命令可以更新名称——Git 使用了创建.lock 文件的谨慎顺序。例如,要更新refs/heads/master,Git 首先创建refs/heads/master.lock1 主机操作系统必须(并且确实)为此提供“创建文件,但如果它已经存在则失败”操作。

这里可能会出错。例如,假设目录(或文件夹,如果您更喜欢该术语)refs/heads/ 拒绝对正在处理git push 进程的用户 ID 授予 create-new-file 权限。在这种情况下,创建 master.lock 将失败并出现“权限被拒绝”类型的错误。

在您的特定情况下,master.lock 文件已经存在。通常,创建、写入、然后删除或重命名此类文件。但是,如果发生电源故障、系统崩溃或其他 Git 程序突然终止的情况,系统不会处于良好状态。特别是.lock 文件继续存在。

对于电源故障或系统崩溃,可以在系统启动过程中进入并删除挥之不去的.lock文件。实际上,这在大多数服务器上并不常见——人们可以像你一样手动修复他们的 Git 服务器。 Git 程序通常不应该被操作系统突然杀死,但有些系统使用“内存不足杀手”(OOM-killers),有时会导致此类问题。


1创建了合适的.lock文件后,Git会继续将新值写入锁定文件,然后使用原子重命名操作将master.lock文件更改为文件命名为master,删除任何以前的文件。这两者都释放锁并存储新值,所有这些都以使得任何需要该值的 other Git 命令都能看到新值。

Git 在更新其索引文件时使用相同的技术来创建index.lock,但由于索引条目永远不会从一个 Git 转移到另一个 Git,因此这里的任何故障总是纯粹是本地的,而不是在 git push 期间。这种技术还有一个特点,就是“事务”可以通过简单地删除锁文件来“回滚”,而不是把锁文件重命名为主名称。

在使用数据库时请记住术语ACID:原子性、一致性、隔离性、持久性。 .lock 文件技术提供原子性,如果操作系统做出正确的保证,则提供一致性和持久性。但是,隔离属性完全缺失:我们不能单独更新一个数据库字段。这就是 为什么Git 对每个引用使用单独的文件(除非,也就是说,当它不使用时,通过 packed-refs 文件,因此它实际上是只读的:只有一个 Git 程序,@ 987654343@,永远更新它,使用它自己更复杂的锁定)。

在处理非常大的索引时,缺乏隔离也会很痛苦。出于这个原因,Git 可以使用“拆分索引”模式,其中一些条目(最近未更改的条目)位于第二个文件中,而只有“主动更改”的条目位于主 .git/index 文件中。

(使用真实数据库可以同时解决所有这些问题,但真实数据库很复杂。)

【讨论】:

    【解决方案2】:

    首先检查git ls-remote 返回的内容。

    目标是确保没有:

    • 远程分支名为master/xxx (as in here)
    • 名为Master 的远程分支(不同的大小写:也请检查您本地的.git/refs/heads 是否有相同的问题)

    【讨论】:

    • 太好了,这也是我的研究成果。所以,我并没有疯狂。如果 OP 发生这种情况,我会感到惊讶,因为我假设它是一个新的 git 存储库,它具有默认的 master 分支。但是,我能找到的有关此错误的所有信息都让我相信情况并非如此。
    猜你喜欢
    • 2019-10-16
    • 1970-01-01
    • 2014-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 2019-07-16
    相关资源
    最近更新 更多