【问题标题】:git: pruning / removing old branches: "error: failed to push some refs"git:修剪/删除旧分支:“错误:未能推送一些参考”
【发布时间】:2020-03-06 07:37:53
【问题描述】:

这是我的 GitHub 存储库中一些远程分支的列表:

$ git branch -a  

warning: ignoring broken ref refs/remotes/remote/HEAD
* master
  origin
  restoration-effort2
  remotes/origin/master
  remotes/remote/master
  remotes/remote/carousel
  remotes/bridgent/animate
  remotes/bridgent/enlarged-hover
  remotes/bridgent/master
  remotes/bridgent/Rayom-generator-app
  remotes/bridgent/scripts
  remotes/bridgent/bridgent-carousel

我在这里的意图/目标是删除所有以“remotes”开头的那些(但不是两个“master”)。

当我尝试删除它们时,我得到:

error: unable to delete 'remote/bridgent-carousel': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<project_name>.git'

所以我谷歌“错误:无法删除远程引用不存在”,它出现了一个标题为 Git says remote ref does not exist when I delete remote branch 的 SO 问题/答案

我发现的另一个指南(包括类似的建议,但合并成一篇有用的博客文章)可以在 here 找到。

这两个指南建议使用如下命令:

$ git branch -D animate
$ git push origin --delete remotes/Rayom/animate
$ git fetch --prune
$ git push origin --delete <branch_name>

在我的例子中,这些命令帮助我消除了许多不再需要的旧分支,但是这些命令不会删除剩余的分支(如上所列)。输入这些命令(包括一些变体)会产生以下输出:

$ git push origin --delete bridgent/Rayom-generator-app                        
error: unable to delete 'bridgent/Rayom-generator-app': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<project_name>.git'

$ git push origin --delete remote/bridgent-carousel 
error: unable to delete 'remote/bridgent-carousel': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<project_name>.git'

$ git push origin --delete Rayom-generator-app 
error: unable to delete 'Rayom-generator-app': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<project_name>.git'

$ git push origin :Rayom-generator-app 
error: unable to delete 'Rayom-generator-app': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<project_name>.git'

$ git branch --remote
<no output>

$ git remote prune origin --dry-run
<no output> 

$ git remote prune origin          
<no output>

所以我对你们所有人的主要问题是:如何删除remotes/bridgent/Rayom-generator-app 和所有类似的远程分支?

还值得注意的是,当我将 origin 替换为 remote 时,我得到了类似的输出,但这里的不同之处在于远程引用了以前的 git 项目的名称(不再存在):

$ git push remote --delete bridgent/Rayom-generator-app 
error: unable to delete 'bridgent/Rayom-generator-app': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<**former**_project_name>.git'

$ git push remote --delete remote/bridgent-carousel 
error: unable to delete 'remote/bridgent-carousel': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<**former**_project_name>.git'

$ git push remote :Rayom-generator-app 
error: unable to delete 'Rayom-generator-app': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<**former**_project_name>.git'

【问题讨论】:

  • 这个错误是因为origin远程(大概是你的GitHub repo)中没有任何名为bridgent/Rayom-generator-app的分支。相反,在名为 bridgent 的远程中有一个名为 Rayom-generator-app 的分支,它指向其他存储库的 URL。

标签: git github


【解决方案1】:

TL;DR

运行git remote 并查看您是否有名为remotebridgent 的遥控器。 (使用git remote -v 查看与每个遥控器关联的 URL。)

如果您不想拥有名为remote 的遥控器,请使用git remote remove remote 将其删除。这也将删除其所有远程跟踪名称。如果需要,对 bridgent 重复。

如果您确实想要保留这些遥控器,但要删除与这些遥控器关联的任何远程跟踪名称,请运行:

git fetch remote --prune

和/或:

git fetch bridgent --prune

你也可以运行:

git fetch --all --prune

(或简称git fetch -a -p)。 --all 表示联系所有遥控器。或者,您可以使用git remote update --prunegit remote update 默认从所有遥控器获取。 git fetch 的默认值通常只是调用并因此更新 origin1


1技术上,git fetch 的默认值是根据当前分支的 upstream 调用远程,但如果没有设置,它使用 @ 987654339@。大多数 Git 存储库往往只有一个远程,名为 origin,所以这很好用。您的 Git 存储库有 三个 远程,所以它没有。

git remote update 的默认值特别复杂;有关详细信息,请参阅its documentation。这似乎是为大型镜像站点设计的,例如我曾经为中型企业设置运行的镜像站点。


让我引用这部分来强调,因为它是:

  remotes/origin/master
  remotes/remote/master
  remotes/remote/carousel
  remotes/bridgent/animate
[snip]

如果我们从每一行中取出remotes/ 部分,我们得到:

origin/master
remote/master
remote/carousel
bridgent/animate
bridgent/enlarged-hover
bridgent/master
[snip]

如果我们从剩余的第一个 / 开始进一步删除该部分,并消除重复项,我们会得到以下列表:

origin
remote
bridgent

这是遥控器的列表。

如果您运行git remote,您应该会看到这个相同的名称列表。 (如果您不这样做,我们要解决的问题与我认为您遇到的问题有些不同。)

现在:

这是我的 GitHub 存储库中一些远程分支的列表:

从技术上讲,这些不在您的 GitHub 存储库中。它们位于您的 本地 存储库中(或位于)您的笔记本电脑或台式计算机上。 GitHub 上有另一个不同的存储库;那个是你的 GitHub 存储库。

远程和远程跟踪名称

请记住,Git 是一个分布式版本控制系统。因此,通常有两个、三个、十个甚至数百万个存储库。每个存储库都有自己的分支名称。某些存储库的所有克隆共享的不是分支,而是提交commits 是共享的。 分支名称只是帮助每个存储库记住提交。每个提交都有一个唯一的哈希 ID,它在 每个 存储库中都是相同的。存储库确实具有该提交,然后具有该哈希ID;或者它没有那个提交,也没有那个哈希 ID。

当你的 Git 调用 GitHub 上的另一个 Git 时,你的 Git 会询问他们他们的提交。他们会说,例如,我有我的 master 作为提交 a123456... 你的 Git 检查:我有 a123456... 吗? 如果你 em> 有它,你的 Git 说 好的,我已经有了它,你不需要得到它。如果你没有拥有它,你的 Git 会说啊,请给我a123456...,他们的 Git 现在提供了它的 parent 提交犯罪。你的 Git 检查你是否有 that 提交。如果没有,您的 Git 会询问 a123456... 的父级,然后他们会提供该提交的父级(a123456... 的祖父级),而您的 Git 会检查该哈希 ID,等等。

最后,你的 Git 从他们的 Git 中获得所有他们在 master 上的提交,而你的 Git 根本没有这些提交。所以现在你有你所有的提交加上他们所有的提交。你的master 很可能成为这个a123456... 提交。或者,您的 master 可能是其他一些提交。无论是哪种情况,您的 Git 现在都会创建一个新名称,或更新现有名称,以记住 他们的 master

您的 Git 对其 Git 分支名称的记忆是您对这个特定的“其他 Git”的远程跟踪名称。 GitHub 上的另一个 Git 有一个 URL; remote 名称 origin 存储此 URL。但是如果你有不止一个“其他 Git”呢?

您的 Git 可以调用一个不同的 Git 存储库,可能名称为 bridgent。这个远程名称 bridgent 存储一个 URL。这就是你的 Git 将调用 this 其他 Git 的方式。当你的 Git 调用另一个 Git 时,他们会说:我有一个名为 animate 的分支、一个名为 enlarged-hover 的分支和一个名为 master 的分支。我的animate 是提交b789abc...,我的enlarged-hover 是提交fedcba9...,我的master 是...

你的 Git 将从 bridgent Git 获得 拥有的任何提交,而你没有。然后您的 Git 将创建或更新您的 bridgent/* 名称。这些包含您的 Git 从您的 Git 以名称 bridgent 存储其 URL 的 Git 获得的哈希 ID。

所以,既然你有origin remote bridgent,这意味着你的Git已经记录了三个独立的遥控器 .每个遥控器存储一个 URL;在那个 URL 上,当你拨打它的号码时,一些 Git 会应答。 那个 Git 有一个分支名称列表。每个分支名称通过哈希 ID 标识一些特定的提交。 你的 Git 确保它也有这些提交,然后为每个其他 Git 存储库创建或更新 远程跟踪名称

您的 Git 调用的 Git 的远程跟踪名称 origin 列在 origin/* 下。您的 Git 调用的 Git 的远程跟踪名称 remote 列在 remote/* 下。您的 Git 调用的 Git 的远程跟踪名称 bridgent 列在 bridgent/* 下。这就是你的 Git 保持所有这些东西的方式。

git branch -a 打印remotes/origin/master

如果你使用:

git branch

您的 Git 列出了您的分支名称。它们以masterdevelop 等形式出现。

如果你使用:

git branch -r

您的 Git 列出了您的远程跟踪名称。它们以origin/masterbridgent/animate 等形式出现。

两套名称都被缩短。您的master 的实际全名是refs/heads/masterorigin/master的实际全名是refs/remotes/origin/masterbranch 名称已删除 refs/heads/remote-tracking 名称 已删除 refs/remotes/

将这些前缀放回保证名称不会发生冲突。如果出于某种奇怪的原因,您创建了自己的名为origin/master 的本地分支,它的实际全名将是refs/heads/origin/master。您的远程跟踪origin/master 真的是refs/remotes/origin/master。显然,这两个名字是不同的,因为 prefix 部分不同。由于 Git 在内部使用全名,所以 Git 不会感到困惑......但是自从 Git 和你,看到 缩短的 名字, 可能会感到困惑。不要创建名为 origin/master!2

的本地分支

不过,无论出于何种原因,git branch -a 在列出远程跟踪名称时只会删除refs/ 部分。所以git branch -a 向您展示了remotes/origin/masterorigin/masterremotes/remote/carouselremote/carousel,等等。

如果您愿意,可以使用git branch 命令删除远程跟踪名称:给它-d -r,即删除 远程选项。

不能——至少,没有成功——让你的 Git 请求位于 origin 的 Git 删除 remote/bridgent-carousel

$ git push origin --delete remote/bridgent-carousel 
error: unable to delete 'remote/bridgent-carousel': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<project_name>.git'

因为origin 的 Git 没有这个名字。位于bridgent 的Git 有——或者至少曾经有过——名称carousel。如果您有权限,您可以要求 他们 将其删除。或者,您可以删除 Git 存储库中的 remote。远程名称 bridgent-carousel 存储 URL,并使您的 Git 具有bridgent/* 或更完整的refs/remotes/bridgent/* 形式的远程跟踪名称。


2如果你这样做,你可以写refs/heads/origin/masterrefs/remotes/origin/master,或者只写heads/origin/masterremotes/origin/master,以保持它们的正确性。执行此操作的时间足以重命名或删除名为 origin/master 的本地分支。

【讨论】:

  • 我很高兴有像@torek 这样的高级社区 SO 贡献者投入如此多的精力、时间和精力来回答我的新手问题。我现在有一个详细的资源,它解释了在我的项目上下文中管理本地和远程 git 存储库的细微差别。我会经常提到这一点。谢谢你,托雷克。 =)
【解决方案2】:

这里是:

$ git remote -v
origin  git@github.com:Nostrad/<project_name>.git (fetch)
origin  git@github.com:Nostrad/<project_name>.git (push)
remote  git@github.com:Nostrad/<former_project_name>.git (fetch)
remote  git@github.com:Nostrad/<former_project_name>.git (push)
bridgent git@github.com:bridgent/<project_name>.git (fetch)

我想既然有一个名为“remote”的远程,它指向一个不再存在的 URL。

所以我跑了:

$ git remote remove remote

然后:

$ git remote remove bridgent
$ git fetch --prune
$ git push origin --delete

上面的一些内容可能是不必要或多余的,但我还是调用了它们,因为我是新手。

这是我的树,去掉了所有过时的树枝:

git branch -a
warning: ignoring broken ref refs/remotes/remote/HEAD
* master
  origin
  restoration-effort2
  remotes/origin/master

我已经达到了我的最终结果。在查看 @torek 极其详细和有用的解释之前,我已经完成了最初的目标。所以我没有机会尝试他的 TL;DR 建议:

$ git fetch remote --prune
$ git fetch bridgent --prune
$ git fetch --all --prune

【讨论】:

    猜你喜欢
    • 2013-03-15
    • 2021-08-07
    • 2022-01-25
    • 2012-04-07
    • 2012-08-16
    • 2021-03-26
    • 2017-12-07
    • 1970-01-01
    • 2018-03-27
    相关资源
    最近更新 更多