Git - 啥是“Refspec”
Posted
技术标签:
【中文标题】Git - 啥是“Refspec”【英文标题】:Git - What is "Refspec"Git - 什么是“Refspec” 【发布时间】:2017-11-04 03:08:57 【问题描述】:我一直在关注this guide 配置 GitLab 与 Jenkins 的持续集成。
作为该过程的一部分,需要按如下方式设置 refspec:+refs/heads/*:refs/remotes/origin/* +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*
为什么有必要在帖子中没有解释,所以我开始在网上寻找解释并查看了official documentation以及一些相关的***问题like this one。
尽管如此,我还是一头雾水:
究竟什么是 refspec? 为什么上面的 refspec 是必要的——它有什么作用?
【问题讨论】:
这是相当广泛的 - 你具体没有从例如那个文件? 【参考方案1】:refspec 告诉 git 如何将引用从远程映射到本地 repo。
您列出的值为+refs/heads/*:refs/remotes/origin/* +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*
;所以让我们分解一下。
你有两个模式,它们之间有一个空格;这只是意味着您要给出多个规则。 (专业的 git 书将此称为两个 refspecs;这在技术上可能更正确。但是,如果需要,您几乎总是能够列出多个 refspecs,因此在日常生活中它可能没什么区别。)
那么,第一个模式是+refs/heads/*:refs/remotes/origin/*
,它包含三个部分:
+
表示应用规则不会失败,即使这样做会以非快进方式移动目标引用。我会回到那个。
:
之前的部分(如果有,则在+
之后)是“源”模式。那是refs/heads/*
,这意味着此规则适用于refs/heads
下的任何远程引用(意思是分支)。
:
之后的部分是“目标”模式。那是refs/remotes/origin/*
。
所以如果源有一个分支master
,表示为refs/heads/master
,这将创建一个远程分支引用origin/master
,表示为refs/remotes/origin/master
。等等任何分支名称 (*
)。
回到那个+
...假设原点有
A --- B <--(master)
你获取并应用你得到的 refspec
A --- B <--(origin/master)
(如果您应用了典型的跟踪规则并执行了 pull
,那么您还可以将 master
指向 B
。)
A --- B <--(origin/master)(master)
现在遥控器上发生了一些事情。有人可能做了一个reset
,删除了B
,然后提交了C
,然后强制推送。所以遥控器说
A --- C <--(master)
当你获取时,你得到
A --- B
\
C
并且 git 必须决定是否允许将 origin/master
从 B
移动到 C
。默认情况下,它不允许这样做,因为它不是快进(它会告诉您它拒绝了对该 ref 的拉取),但因为规则以 +
开头,它会接受它。
A --- B <--(master)
\
C <--(origin/master)
(在这种情况下,拉取将导致合并提交。)
第二个模式类似,但对于merge-requests
refs(我认为这与您的服务器的 PR 实现有关;我不熟悉它)。
更多关于参考规范:https://git-scm.com/book/en/v2/Git-Internals-The-Refspec
【讨论】:
谢谢,这个解释很有帮助。为了与您链接到的 Pro Git 书保持一致:他们似乎说+refs/heads/*:refs/remotes/origin/*
+refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*
是 两个 refspec,而不是一个具有两种模式的 refspec。
对于那些来github解决方案的人:git config --local --add remote.origin.fetch +refs/pull/*/head:refs/remotes/origin/pr/*
不要忘记从远程下载refs:git fetch origin
然后你可以checkout到pull-request numbergit checkout pr/1
你也可以看到所有本地引用:git show-ref
如果:
之前的部分为空白怎么办?这是什么意思?
好的,网上找到答案了:Deleting references is done by pushing an empty local reference to it, like you can do with git's push command. So pushing [":refs/heads/i18n"] would delete the i18n branch on the remote.
【参考方案2】:
refspec 告诉 git 如何将引用从远程映射到本地 repo。
在 Git 2.29(2020 年第四季度)中,refspec 还可以告诉 Git 对排除的引用。
“git fetch
”和“git push
”支持负引用。
所以你不仅可以选择性地fetch
:
# Do not fetch any remote branch starting with 'm'
git fetch origin refs/heads/*:refs/remotes/origin/* ^refs/heads/m*
但您甚至可以选择性地push
或push --prune
:
# If I delete local branches, included b,
# those same branches will be deleted in the remote 'origin' repo.
# ... except for the remote branch b!
git push --prune origin refs/heads/* ^refs/heads/b
参见 Jacob Keller (jacob-keller
) 的 commit c0192df(2020 年 9 月 30 日)。(由 Junio C Hamano -- gitster
-- 合并到 commit 8e3ec76,2020 年 10 月 5 日)
refspec
:添加对负参考规范的支持签字人:Jacob Keller
fetch
和push
都支持模式引用规范,允许获取或推送与特定模式匹配的引用。 因为这些模式是全局的,所以它们表达更复杂情况的能力有限。例如,假设您希望从远程获取除特定分支之外的所有分支。为此,您必须设置一组仅匹配所需分支的 refspec。 因为 refspecs 要么是显式名称匹配,要么是简单的 glob,因此许多模式无法表达。
添加对新型 refspec 的支持,称为“否定”refspecs。
它们以“
在获取期间,这指的是遥控器上 ref 的名称。 在推送期间,this 指的是本地端的 ref 名称。^
”为前缀,意思是“exclude any ref matching this refspec
”。 它们只能有一个始终指向源的“侧面”。使用否定的 refspec,用户可以表达更复杂的模式。为了 示例:
git fetch origin refs/heads/*:refs/remotes/origin/* ^refs/heads/dontwant
会将
origin
上的所有分支提取到remotes/origin
,但会排除 获取名为dontwant
的分支。今天的参考规范是可交换的,这意味着顺序并不重要。 否定的 refspecs 总是最后应用,而不是强制一个隐含的顺序。 也就是说,为了匹配,一个 ref 必须至少匹配一个正 refspec,并且不匹配任何负 refspec。 这类似于负路径规范的工作方式。
The documentation 现在包括:
<refspec>
可能在其<src>
中包含*
以指示简单模式 匹配。 这样的 refspec 的功能类似于匹配任何具有相同前缀的 ref 的 glob。模式<refspec>
必须在<src>
和<dst>
。它将通过将*
替换为 内容与源匹配。如果 refspec 以
^
为前缀,它将被解释为否定 参考规范。 这样的 refspec 将改为指定要排除的 refs,而不是指定要获取哪些 refs 或要更新哪些本地 refs。 如果一个 ref 至少匹配一个正 refspec,并且不匹配任何负 refspec,则该 ref 将被视为匹配。负引用规范可用于限制模式引用规范的范围,使其不包含特定引用。 负引用规范本身可以是模式引用规范。然而,他们可能只 包含
<src>
,但不指定<dst>
。 完全拼出的十六进制对象 也不支持名称。
更多示例请参见t5582-fetch-negative-refspec.sh
【讨论】:
对于那些只有本地手册页(v2.31 版本)的人,文档将位于git help pull
和 git help fetch
中。以上是关于Git - 啥是“Refspec”的主要内容,如果未能解决你的问题,请参考以下文章
Git:在 Git 中推送提交时消息“src refspec master does not match any”
Git:错误:error:src refspec master does not match any
使用 Git 报错 error: src refspec master matches more than one.
git commit时出错:error: src refspec master does not match any
git报错error: src refspec refs/heads/master does not match any.