使用完整的refspec进行Git push无法工作

3

我有两个分支(本地和github上)。 我将它们称为BranchA和BranchB。 我在BranchA中有提交c1、c2和c3。 我只有c1的BranchB。 这两个分支都已经更新到github,我可以检查BranchA有c1、c2和c3,而BranchB只有c1。

我想从本地的BranchA推送到远程的BranchB。为了做到这一点,我尝试:

git push origin refs/heads/BranchA:refs/remotes/origin/BranchB

当我这样做时,我得到了一个奇怪的输出:
Total 0 (delta 0), reused 0 (delta 0)
To https://github.com/<username>/<repo>.git
   <hash>  BranchA -> origin/BranchB

当我访问Github时,我发现BranchB没有更新,仍然只有c1。然后,如果我再次运行命令,它会返回一切都是最新的。

这让我感到困惑,但更糟糕的是,当我尝试执行不带完整引用的命令时,就像这样:

git push origin BranchA:BranchB

...它起作用了。

我对此非常困惑。我搜索了一下,认为使用完整的引用(例如/refs/heads/)不会有任何问题。

为什么会发生这种情况?当我指定完整的分支名称时,它不应该起作用吗?


出于好奇,你为什么使用了完整的引用规范? - evolutionxbox
4
命令中针对BranchB的远程完整引用规范为refs/heads/BranchB。 - prahlad venkata
@evolutionxbox 没有特别的原因,我只是想尝试使用“不太可能失败”的方式来设置完整路径。但我错了 :) - phansh
@prahladvenkata 是的,似乎是这样。谢谢。 - phansh
1个回答

4

正如prahlad venkata评论所说,远程引用名称为refs/heads/BranchB,而不是refs/heads/remotes/BranchB

请记住,在使用git push或其对应命令git fetch时,涉及到两个Git和两个存储库。我们称之为你的(matovski's)和GitHub的存储库。

您的Git有一个名为BranchA的分支,其完整名称为refs/heads/BranchA。该名称存储一个哈希ID。

他们的Git有一个名为BranchB的分支,其完整名称为refs/heads/BranchB。他们的Git可能也有一个名为BranchA的分支。这些名称也存储哈希ID(每个名称各一个)。

当你的Git与GitHub的Git通信时,你的Git会看到他们的refs/heads/BranchArefs/heads/BranchB。你的Git希望记住这两个名称和ID对,但如果你的Git将它们存储为refs/heads/BranchArefs/heads/BranchB,你的Git将覆盖自己的分支。因此,你的Git将重命名他们的分支名称,用refs/remotes/origin/替换refs/heads/
换句话说,refs/remotes/origin/BranchB你的 Git 对 他们的 Git 的 refs/heads/BranchB 的记忆。但当你的 Git 与他们的 Git 进行通信时,你的 Git 必须告诉他们的 Git:请设置你的 refs/heads/BranchB。如果你的 Git 要求他们的 Git 设置它们的 refs/heads/origin/BranchB,那将设置他们的 Git 对第三个 Git 的 refs/heads/BranchB 的记忆(正如你刚才看到的那样,有时是可以允许的!但在这种情况下没有任何有用的效果,因为 GitHub 的 Git 存储库不会单独使用它们)。
当您使用简写语法git push origin BranchA:BranchB时,您的Git会向对方Git发送一个请求来设置BranchB。他们的Git根据此请求确定,您可能想要设置他们的refs/heads/BranchB,并执行(它认为)您的意图,而不是您所要求的操作。这个特殊技巧只在他们已经有refs/heads/BranchB时才起作用,因为如果他们还没有该分支,他们的Git将不会尝试猜测。

所以,在这种情况下,因为我将信息传递到远程,我指向了错误的一个。明白了。好答案!谢谢。 - phansh

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