完整的错误信息如下:
远程:错误:无法锁定引用 'refs/heads/fix/add_overlay':引用已经存在
我正在使用SourceTree,但我认为这并不重要。我一直在尝试推送,但我一直收到此错误消息,我该如何解决?
fix
,即他们的refs/heads/fix
,我怀疑它挡住了路。(确保他们不介意你移除它!)
refs/heads/fix/add_overlay
存在,那就不是问题!Git应该能够锁定它,如果它不能,它无法锁定的原因不是“因为它存在”。refs/heads/fix
——而不是refs/heads/fix/add_overlay
——存在,所以无法创建一个目录refs/heads/fix/
来保存子参考refs/heads/fix/add_overlay
,因为现有的引用refs/heads/fix
挡住了路。git ls-remote
或者在git fetch -p
之后,查看基于他们的分支名称的远程跟踪名称集合)来确定是否为此情况。如果是这种情况,您应该说服他们——无论他们是谁——重命名或删除他们的分支fix
,这样您就可以让他们创建一个名为fix/
的目录,其中包含诸如fix/add_overlay
之类的分支名称。Fix
的拼写大写了。服务器上是否存在大小写敏感的 fix
和 Fix
,并且可能存在大小写折叠问题? - torek要消除这个错误,导航到您的项目目录并运行git remote
,然后通过运行git remote rm origin
删除origin。创建一个新的存储库,[假设您使用GitHub]通过运行git remote add origin https://github.com/your_user_name/your_repository_name.git
,并将更改推送到远程服务器git push -u origin master
。这应该可以解决问题。
git merge <commit id>
。
6. 继续推送到远程仓库。$ git push
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 8 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 13.43 KiB | 2.69 MiB/s, done.
Total 7 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3), completed with 2 local objects.
To https://github.com/theaccount/therepo.git
92bc4d8..37c3af9 feature/the-branch -> feature/the-branch
error: update_ref failed for ref 'refs/remotes/origin/feature/the-branch': cannot lock ref 'refs/remotes/origin/feature/the-branch': 'refs/remotes/origin/feature' exists; cannot create 'refs/remotes/origin/feature/the-branch'
这个问题往往会反复出现,带有一定的变化,从而吸引了各种各样的回答,通常都是“我尝试了这个方法,它有效”,这又会引起评论,如“对我无效,但这个方法有效”。有许多类似的问题和答案,并不一定是一致的,也不太具有解释性:
我想尝试深入一些,揭示git
内部更多的问题。通常在使用Git时,我并不想知道太多。解释通常是违反直觉的,由于缺乏基础背景而导致箭头指向错误的图表不够有用。这次我希望能让某些潜在的概念更加清晰,这可以帮助解决问题,并使将来的情况更容易记住和应用。
我试图保持简短,但请记住:
Git将所有本地数据和记录保存在本地repo的.git
目录中。
当您创建名为feature/the-branch
的(本地)分支时,Git会:
.git/refs/heads/feature/
(如果不存在).git/refs/heads/feature/the-branch
(这只是最初的Git实现决定的方式)origin
)时,Git会创建路径.git/refs/remotes/origin/feature/the-branch
,包括沿途的所有目录(可能有多个远程)。
现在,如果有人(不是我,诚实的)之前创建了一个名为feature
的分支(不要这样做),那么Git将创建一个文件.git/refs/heads/feature
,并且在推送时还会创建另一个文件.git/refs/remotes/origin/feature
。
现在,您应该看到无法创建.git/refs/heads/feature/
目录,并且以feature/
开头的所有分支都被阻止了。
(使用rsync
术语的尾随斜杠来指示目录。)
所有这些内容都在您的本地.git
目录中,在您的本地repo中 - 即使它是为了记录有关远程repo的某些内容,例如.git/refs/remotes/origin/feature/the-branch
。
有时,您可以通过再次从远程克隆来解决问题,但那是作弊。而且需要时间。当您在本地拥有需要推送到原点的内容时,进行手动复制可能会引入难以定位的错误。
在这种情况下,我们确实有一个名为feature
的分支,除了每次查看repo时非常不舒服之外,还阻止了创建与CI / CD工具链的其他部分一起使用所需的feature
分支。
对于这个(旧)问题(没有被接受的答案),看起来很像有人曾经创建了一个名为fix
(天才)的分支。如果整个Git问题类型都不能让你考虑命名约定,那我不知道还有什么能让你考虑。我一直讨厌糟糕的命名,但现在我有理由对此感到愤慨。
所以这里的错误信息看起来像是在说refs/heads/fix/add_overlay
已经存在。说实话,它确实是在说这个(再次感谢Git;很高兴看到你保持了你的声誉),但似乎已经存在的引用是refs/heads/fix
。这意味着有一个本地文件.git/refs/heads/fix
,而Git无法像需要的那样创建.git/refs/head/fix/
,因为该路径或引用已经存在。
fix
或在我的情况下,feature
)分支,此情况仍可能存在。或者您可能已经正确清理了源,但本地仍然有引用。即使推送报告错误,推送甚至似乎成功,随后的操作仍然会失败。
似乎会出现一系列问题和错误消息,这些错误消息可能与类似的情况有关。请记住需要包括正确目录和文件名的本地引用路径,以下消息在回顾时都更加合理:
在我的情况下,我不知何故已经成功推送到该分支。它存在于远程,但是现在,在另一个推送莫名其妙地失败后,我无法再连接。Git告诉我我的上游分支已经“消失”:
$ git branch -vv
develop f22092e [origin/develop] Update deploy.yml
* feature/the-branch 37c3af9 [origin/feature/the-branch: gone] Move old README.md into documentation
main 7bd2f45 [origin/main] Delete Deploytonon-prod.yml
release 3b90d28 [origin/release] Merge pull request #10 from theaccount/develop
On branch feature/the-branch
Your branch is based on 'origin/feature/the-branch', but the upstream is gone.
(use "git branch --unset-upstream" to fixup)
我尝试重置上游连接,但问题显然仍然存在:
$ git branch --unset-upstream
$ git branch --set-upstream-to=origin/feature/the-branch feature/the-branch
error: the requested upstream branch 'origin/feature/the-branch' does not exist
我尝试从源更新以重新对齐(或其他操作),但Git已经陷入了死胡同:
$ git fetch
error: cannot lock ref 'refs/remotes/origin/feature/the-branch': 'refs/remotes/origin/feature' exists; cannot create 'refs/remotes/origin/feature/the-branch'
From https://github.com/theaccount/therepo
! [new branch] feature/the-branch -> origin/feature/the-branch (unable to update local ref)
在使用修复所有问题的 git
一行命令之前,我想展示一些我在 git
技能库中没有考虑到的视图。
git branch -vv
不显示错误引用,因此它是不可见的。
最终,你可以执行 $cd .git
并开始查看: ls refs/heads
。这可能是最快的方法。但为了总结远程和本地的情况,以下两个命令立即揭示了问题。
$ git ls-remote
From https://github.com/theaccount/therepo.git
7bd2f45d5a7a137c1058c2074183ff0dc4c523b7 HEAD
f22092ebd8f9c243efaf770f941cddf0f9b916c5 refs/heads/develop
37c3af9fe595c427eb1ff1d194e742e5273633c1 refs/heads/feature/the-branch
5317d3f80b94ab721ee2c51b87b70e950241fe01 refs/heads/features/notification
7bd2f45d5a7a137c1058c2074183ff0dc4c523b7 refs/heads/main
3b90d28ef5e5b1d4ad45b17bfa98d10cc70cdef5 refs/heads/release
9b169e74da97174d4877e7359c1772287faf03bb refs/pull/1/head
f22092ebd8f9c243efaf770f941cddf0f9b916c5 refs/pull/10/head
96a8240b0449dff6579629de6feede0d82120765 refs/pull/2/head
8d1e7d64f276b9927dfd1b664805b208a421c6c9 refs/pull/3/head
0d120fee6da456d2f953a4aaa57f577489f21501 refs/pull/4/head
4ab5cc4596f31b44f72e3a0d92c8143b0cf39b2c refs/pull/5/head
84ad3d7d7856d44fd45592d083e284964c19f1ef refs/pull/6/head
881bfa14baa0b2d15e013371415cb3bf912b2887 refs/pull/7/head
b89c797b4abe0676cfdbfcbb09ffb87897a06eef refs/pull/8/head
d40fdb24faea617f35c045a73e1884952e9283bf refs/pull/9/head
b345722255e495cdd8895e7d53357dd8a3de523c refs/tags/v0.0.0
28f027de3f6e8c8f541f22eea4fa25eba3ce15ce refs/tags/v0.0.0^{}
5317d3f80b94ab721ee2c51b87b70e950241fe01 refs/tags/v1.0.0
查看源代码,没有refs/heads/feature
。这个问题已经被另一个开发人员解决了,这不是阻碍因素。我们正在尝试访问的分支在那里列出为refs/heads/feature/the-branch
,正如它应该的那样。我们甚至可以看到为什么去年我们在标记v0.0.0
时遇到了问题,因为在refs/tags/v0.0.0^{}
中的一个标记名称中似乎存在一个键跳动。
但是本地Git认为远程分支是什么呢?
$ git branch -r
origin/HEAD -> origin/main
origin/develop
origin/feature
origin/features/notification
origin/main
origin/release
就本地而言,我们可以看到仍然有一个对于“origin”“特性”分支的引用,即使它已经从远程删除(并且在本地从未存在过(记住,我说不是我!))。重新开始一个新的repo(从头克隆)将避免这个问题(现在“origin/feature”已被删除),但正如我们所说,这是费力和容易出错的,你甚至可以尝试使用“rm origin/feature”,但还有更好的方法。
现在我们想要删除一些东西;像Git(或任何东西一样,但以某种方式,它在Git中总是更加复杂)一样,我们希望确保我们不会删除错东西。希望这背景介绍了更多信心。如果您仍然认为可能发生不可挽回的破坏性事件,您始终可以压缩repo并将其放在手边,以便在搞砸时再次尝试;但现在应该真的不需要这样做。
我们有我们的本地分支,并进行了更改以进行推送,但upstream显示错误,所以我们可以清理它:
$ git branch --unset-upstream
现在我们有了一个没有任何跟踪的本地分支:
$ git branch -vv
develop f22092e [origin/develop] Update deploy.yml
* feature/the-branch 37c3af9 Move old README.md into documentation
main 7bd2f45 [origin/main] Delete Deploytonon-prod.yml
release 3b90d28 [origin/release] Merge pull request #10 from theaccount/develop
fetch
从origin
获取分支信息,但我们添加了--prune
选项,以使命令剥离与原始版本不对齐的本地引用。这将删除阻止的feature
(文件)并创建到feature/the-branch
的远程引用:$ git fetch --prune origin
From https://github.com/theaccount/therepo
- [deleted] (none) -> origin/feature
* [new branch] feature/the-branch -> origin/feature/the-branch
现在本地 Git 已经有了正确的引用,我们可以轻松地将本地分支的上游设置为源上的分支。名为 feature
(或 OP 的 fix
)的文件已被删除,并被同名目录所替代:
$ git branch -u origin/feature/the-branch
Branch 'feature/the-branch' set up to track remote branch 'feature/the-branch' from 'origin'.
检查我们的分支状态,显示所有跟踪其远程的分支:
$ git branch -vv
develop f22092e [origin/develop] Update deploy.yml
* feature/the-branch 37c3af9 [origin/feature/the-branch] Move old README.md into documentation
main 7bd2f45 [origin/main] Delete Deploytonon-prod.yml
release 3b90d28 [origin/release] Merge pull request #10 from theaccount/develop
现在你应该能够添加
,提交
和推送
了。希望如此。
正如我所说,我认为由于远程和源上的故障组合可能会出现一系列类似的问题。如果您的情况与fetch --prune
不匹配,则请查看本答案开头的问题列表并研究可能涵盖相反情况的命令:
git remote prune origin