Git推送错误:dst refspec refs/heads/main匹配多个。

17
当前我被迫在每次更改时推送到一个新的分支。并且该分支必须被删除,因为错误会再次出现在每个新创建的分支上。 git push origin main 输出以下内容。
error: dst refspec refs/heads/main matches more than one
error: failed to push some refs to 'https://github.com/CarloCattano/fastesTube'

我的 git tag 输出:
refs/heads/dev
refs/heads/dev2
refs/heads/dev3
refs/heads/main
v1.1
win64 

无论我是否使用-d手动删除它们,问题都还存在。甚至尝试将项目迁移到新的存储库,但在进行几次推送后问题仍然存在。 git remote -v
origin  https://github.com/CarloCattano/fastesTube (fetch)
origin  https://github.com/CarloCattano/fastesTube (push)

git ls-remote

ac4cac50b79ff682ddd01f6c0c3913d0bd765e64        HEAD
77273d612953f96e72ce305ab94f0a535a4c332d        refs/heads/dev3
3c344e7af2feb33db2d05f08866cad5fe624b57c        refs/heads/develop
ac4cac50b79ff682ddd01f6c0c3913d0bd765e64        refs/heads/main
fde3bb1ed7c770a5b8eb94a368bb34f25566f00e        refs/pull/1/head
ffe33059c3fcc12899953bc588772072d9a18bf0        refs/pull/2/head
77273d612953f96e72ce305ab94f0a535a4c332d        refs/pull/3/head
3c344e7af2feb33db2d05f08866cad5fe624b57c        refs/pull/4/head
b9d1c3f8b83ea1ac868143ec647776d03f9bacc7        refs/tags/refs/heads/dev
ffe33059c3fcc12899953bc588772072d9a18bf0        refs/tags/refs/heads/dev2
77273d612953f96e72ce305ab94f0a535a4c332d        refs/tags/refs/heads/dev3
4098ea71b5a0873db6be41e859e5b8242d81c708        refs/tags/refs/heads/main
a42341ba40635bd5063a0bf988eab6c00b0e62d1        refs/tags/v1.1
37220afec1d13dcac99c61ef766ac800fc6438f5        refs/tags/win64

“Force pushing” 似乎也无效。
可能是我错误地配置了 .yml 文件,并为每个发布创建了标签。
4个回答

38

问题在于您创建了名为refs/heads/...(填写三个点)的标签。

Ref引用是Git中的一个字符串,通常以refs/开头并带有命名空间限定符:

  • refs/heads/*是分支名称:匹配*的部分是分支名称;
  • refs/tags/*是标签名称:匹配*的部分是标签名称;
  • refs/remotes/*是远程跟踪名称;

等等。通常,您可以给Git一个缩短的名称,例如mainv1.1,它可以通过查看现有名称来确定此名称是分支名称还是标签名称:

  • 通常会有一个refs/heads/mainrefs/heads/master,但没有refs/tags/mainrefs/tags/master,因此mainmaster因此是分支名称。
  • 可能会有一个refs/tags/v1.1,但通常如果没有refs/heads/v1.1,则v1.1因此是标签名称。

使用这种方案时,您提供一个不明确的名称,如mainv1.1,Git会自行确定它是分支名称还是标签名称,或者您提供一个完整名称,例如refs/heads/main,Git立即知道它是分支名称。没有refs/heads/refs/tags/限定符的短名称是一个未限定的名称。全名是一个限定名称

git push命令比大多数其他Git命令(除了git fetch类似复杂)更为复杂,因为它必须处理两个 Git存储库,而不是只有一个。因此,git push可以采用refspec,它是由冒号:分隔的两个引用组成的一对。如果您使用完整的refspec:

git push origin refs/heads/main:refs/tags/v1.2

左右两边的部分都是引用(refs),每个引用可以是未经过限定或已被限定。 未经过限定的名称可以通过查看本地Git存储库的名称(对于本地存储库)或远程的名称(对于远程存储库)来解析。

但是,如果您使用部分 refspec:

git push origin main

由于 Git 不确定您是指“本地找到的 main”还是“远程找到的 main”,因此 Git 会在两个位置查找以做出最佳猜测。

然而,在这种情况下,目标 Git(在您的git ls-remote输出中显示其引用的Git)同时拥有 refs/heads/mainrefs/tags/refs/heads/main 引用。所以,您的 Git 已经在本地查找了main并找到了 refs/heads/main;现在它在另一个 Git 存储库的引用集中查找该引用,并且由于refs/heads/main既是完全限定的分支名称,也是完全限定的tag名称之一,因此无法将其转换为只有一个引用。结果就是你会得到这个错误信息。

我不知道对于 git push origin refs/heads/main:refs/heads/main 是否会出现这个错误。但最好的解决方法是纠正目标上的名称集,以便不再存在 refs/tags/refs/* 的名称。也就是说,这四个名称:

b9d1c3f8b83ea1ac868143ec647776d03f9bacc7        refs/tags/refs/heads/dev
ffe33059c3fcc12899953bc588772072d9a18bf0        refs/tags/refs/heads/dev2
77273d612953f96e72ce305ab94f0a535a4c332d        refs/tags/refs/heads/dev3
4098ea71b5a0873db6be41e859e5b8242d81c708        refs/tags/refs/heads/main

应该适当调整(或完全删除),以使 GitHub 上 Git 存储库中没有任何标签名称以 refs/ 开头。理想情况下,这些标签名称也不应与任何分支名称匹配: 标签名称通常应符合 v * 形式,或符合其他明显的“标记”模式,以便没有人会错误地认为它们是分支名称,反之亦然。

修复后,简单的 git push 命令将再次起作用。


1
非常感谢您提供如此详细的答案。删除标签和额外分支解决了问题。只是遇到了有趣的“电子邮件隐私设置”错误,不得不将其还原为公共状态才能推送,但问题已经解决了。再次感谢您提供如此详尽有用的回答! - Carlo Cattano

2

正如正确解释的那样,存在标签冲突。我在GitHub网站上看到我的标签未列出(没有被远程推送)。问题标签实际上是一个被GitHub桌面误解为标签的分支名称。

错误指示了问题标签。使用git tag命令列出了该标签。

以下命令允许在GitBash中删除标签(如先前共享):

git tag --delete tagname

之后,再次可以推送到远程。

我也尝试下载最新的 Beta 版本,因为据说 "使用以这种方式命名的现有分支的存储库仍然可以推送更新到这些分支"。然而,对我来说,使用更新版本的 GitHub Desktop 并没有解决这个问题。


0

更新:不确定这对于多次推送是否可靠! 我似乎遇到了一些奇怪的问题。当查看git ls-remote时,我的分支名称存储在多个引用下。

我通过以下方式解决了这个问题:

git push origin -u --force <sha>:origin/feature/branch

我认为我真正需要的只是前缀 origin/,可能不需要 origin -u

0

My git tag outputs:

refs/heads/dev
...

好消息:自2023年3月起,已不再可能将此类“标签”名称推送到GitHub:

阻止模糊的分支和标签名称(2023年3月)

GitHub 阻止以 refs/ 开头的分支和标签名称。

在幕后,所有 Git 引用都以前缀开头(分支为 refs/heads/,标签为 refs/tags/)。
然而,在典型的使用中,用户很少看到这些前缀,因此它们被 GitHub、Git 客户端和其他工具默默处理。

当类似的字符串用作分支或标签名称可见部分的开头时,这会导致歧义:用户是想要 refs/heads/feature 还是 refs/heads/refs/heads/feature
几乎所有情况下,分支或标签名称前面的 refs/ 是意外的,并且稍后会成为一个问题。

此更改阻止了引入此类名称的新内容。
仍可以向具有此类命名的现有分支推送更新。


仍然遇到了同样的问题,这个仓库是我在2023年四月安装的,所以我不太确定。 - Vincent Tobiaz
@VincentTobiaz 很有趣,这需要向GitHub支持团队报告,因为这个政策应该是由GitHub方面执行的。 - VonC
@VincentTobiaz,请告诉我GitHub支持的回复:我会编辑这个答案。 - VonC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接