我有 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。 然后,如果我再次运行该命令,它会返回所有内容都是最新的。
这让我感到困惑,但自从我尝试在没有完整引用的情况下执行命令后,情况变得更糟,如下所示:
git push origin BranchA:BranchB
...成功了。
我对此很困惑。我搜索了它,我认为使用完整的引用(例如 /refs/heads/)永远不会造成任何伤害。
为什么会这样?当我指定完整的分支名称时它不应该工作吗?
最佳答案
作为prahlad venkata commented , Remote 上的引用是 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 与 GitHub 的 Git 对话时,您的 Git 会看到它们的 refs/heads/BranchA
和它们的 refs/heads/BranchB
。您的 Git 想要记住这两个名称和 ID 对,但是如果您的 Git 将它们存储为 refs/heads/BranchA
和 refs/heads/BranchB
,您的 Git会覆盖你自己的分支。因此,您的 Git 重命名了它们的分支名称,将 refs/heads/
替换为 refs/remotes/origin/
。
换句话说,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 将不会尝试同样的猜测。
关于带有完整引用规范的 Git 推送不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48422135/