Git 使用完整参考规格推送不工作

Git push with full refspec not working

我有 2 个分支(本地和远程 github)。我将它们称为 BranchA 和 BranchB。 我有带有提交 c1、c2 和 c3 的 BranchA。 我只有提交 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。 然后,如果我再次 运行 命令,它 returns 一切都是最新的。

这让我感到困惑,但自从我尝试在没有 完整参考的情况下执行命令 后,情况变得更糟,如下所示:

git push origin BranchA:BranchB

...成功了。

我对此很困惑。我搜索了它,我认为使用完整的参考文献(例如 /refs/heads/)永远不会造成任何伤害。

为什么会这样?当我指定完整的分支名称时它不应该工作吗?

作为,遥控器上的引用是refs/heads/BranchB,而不是refs/heads/remotes/BranchB

请记住,当使用 git push 或其对应物 git fetch 时,有 两个 Git 和两个存储库,涉及过程。我们称这些为您的(matovski 的)和 GitHub 的。

您的 Git 有一个名为 BranchA 的分支,其全名是 refs/heads/BranchA。此名称存储一个(单个)哈希 ID。

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

当您的 Git 与 Git 集线器的 Git 对话时,您的 Git 会看到他们的 refs/heads/BranchA 和他们的 refs/heads/BranchB。您的 Git 想要记住这两个名称和 ID 对,但是如果您的 Git 将它们存储为 refs/heads/BranchArefs/heads/BranchB,您的 Git 将 覆盖你自己的分支。因此,您的 Git 重命名了它们的分支名称,将 refs/heads/ 替换为 refs/remotes/origin/

换句话说,refs/remotes/origin/BranchBGit对他们的记忆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 就不会尝试同样的猜测。