为什么按名称删除远程分支会产生错误,而按 ref 删除不会?

Why does deleting a remote branch by name produce an error while deleting by ref does not?

当我尝试按名称 删除不存在的远程 Git 分支 时,我预计会收到错误消息:

$ git push origin --delete non/existent
error: unable to delete 'non/existent': remote ref does not exist
error: failed to push some refs to 'git@github.com:<_replaced_>.git'
$ echo $?
1

但是,通过 ref 删除相同的分支 (例如取自 .git/config)不被视为错误:

$ git push origin --delete refs/heads/non/existent
remote: warning: Deleting a non-existent ref.
To github.com:<_replaced_>.git
 - [deleted]         non/existent
$ echo $?
0

为什么会这样?这些命令是否等效?

它们不等价。

一个 ref 要么 完全限定 ,即以 refs/ 开头,因此是明确的,要么不是完全限定的,即以除此之外的其他内容开头refs/.

必须将不完全限定的 ref 转换为完全限定的 ref。排位赛取决于您 git push 的目标。如果它没有找到完全合格的 ref,它会向 git push 的来源报告它无法限定 ref.

完全合格的 ref 当然已经完全合格,所以接收 Git 只是说 "ok, that doesn't exist" 因此要求删除的 Git 很高兴地报告裁判不存在。所以 Git 运行 git push --delete 很高兴,认为一切都很好。

有人可以争辩说 Git 执行 git push 以意识到 "I can't qualify that ref for you" 可能 意味着 [=40] 是合理的=] 这又意味着 "whatever ref you meant, it doesn't exist",这可以使 Git 运行 git push --delete 快乐。但事实并非如此。


请注意,对于匹配两种或多种可能性的模糊引用,我观察到以下内容:

server-repo$ git for-each-ref
11ae6ca18f6325c858f1e3ea2b7e6a045666336d commit refs/heads/ambig
222c4dd303570d096f0346c3cd1dff6ea2c84f83 commit refs/heads/branch
e068bdfce2fd992dc396cb4969327ef5c4d39a43 commit refs/heads/fix-signal
d41117433d7b4431a188c0eddec878646bf399c3 commit refs/heads/foobranch
11ae6ca18f6325c858f1e3ea2b7e6a045666336d commit refs/heads/master
11ae6ca18f6325c858f1e3ea2b7e6a045666336d commit refs/tags/ambig
d41117433d7b4431a188c0eddec878646bf399c3 commit refs/tags/tag-foo

和:

client-repo$ git push --delete origin ambig
error: dst refspec ambig matches more than one
error: failed to push some refs to [server URL]