When I try to delete a non-existent remote Git branch by name, I expectedly get an error:
$ 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
However, deleting the same branch by ref (e.g. taken from .git/config
) is not considered an error:
$ 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
Why so? Are these commands equivalent?
They are not equivalent.
A ref is either fully qualified, i.e., starts with refs/
, and is therefore unambiguous, or is not fully qualified, i.e., starts with something other than refs/
.
A not-fully-qualified ref must be converted to a fully-qualified ref. It is up to the target of your git push
to do the qualifying. If it finds no fully qualified ref, it reports back to the source of the git push
that it was unable to qualify the ref.
A fully-qualified ref is of course already fully-qualified, so the receiving Git just says "ok, that doesn't exist" and hence the Git asking for the deletion is happy to report that the ref does not exist. So the Git running git push --delete
is happy and thinks all is well.
One can argue that it would be reasonable for the Git doing the git push
to realize that "I can't qualify that ref for you" probably means "I don't have anything that would match" which in turn means "whatever ref you meant, it doesn't exist", which could then make the Git running git push --delete
happy. But that's not what actually happens.
Note that with an ambiguous ref, that matches two or more possibilities, I observe the following:
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
and:
client-repo$ git push --delete origin ambig
error: dst refspec ambig matches more than one
error: failed to push some refs to [server URL]