有个远端仓库版本管理混乱,计划以后按照这个模式(原文)来管理版本。
现在的版本中同时有 v0.2.x 分支和 v0.2.x tag,当我们试图删除 v0.2.x 分支,git 回答无法完成操作。
git push origin v0.2.x --delete
> error: dst refspec v0.2.x matches more than one.
最权威的莫过于自带的 manual 手册
man 1 git-push
手册中讲到了 <refspec>
的规则:[+]<src-obj>:<dst-ref>
,其中:
src-obj
是提交的标识(或者分支),如 HEAD
,master~4
dst-ref
是远端要被推送到的 ref(引用)dst-ref
为空时,使用 src-obj
同名的 refsrc-ref
为空时,则是删除远端的 dst-ref
所以删除远端分支的语法应该是写作 git push origin :v0.2.x
,嗯,比诡异的 push --delete
语法看起来好理解一些。
不过我们的问题还没有解决,如果有同名的 dst-ref
如何解决,ref
按什么规则书写,如何查看?
其中 SPECIFYING REVISIONS 一节中完整的解释了 <refname>
的表示,下面是我自己的理解。
refs/xxx/<refname>
这样一个层级名称HEAD
,FFETCH_HEAD
和 ORIG_HEAD
等实际上是特殊的别名(类似 shell 里的 alias)refs/heads/master
名称,而只用 master
,git 会匹配出完整的 refname。但有歧义时会提醒我们(就是本文开始遇到的问题)这里不精确的类比一下
手册中解释了 git 如何来匹配 refname 的全名,实质上在 .git
目录下,我们就能看到这些文件,文件的内容正是指向提交的 sha1 串
.git/HEAD
.git/refs/heads/master
.git/refs/heads/v0.2.x
.git/refs/tags/v0.2.x
.git/refs/remotes/origin/master
...
到这里我们的问题就很好解决了:只需要用完整的 refname 进行操作就行:
git push origin :refs/tags/v0.2.x