我一直关注this guide配置GitLab与Jenkins的持续集成。
作为整个过程的一部分,有必要将respec设置如下
+refs/heads/*:refs/remotes/origin/* +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/
*
为什么这有必要没有在帖子中解释,所以我开始在网上寻找解释并查看official documentation以及一些相关的堆栈溢出问题like this one。
尽管如此,我还是很困惑 -
refspec究竟是什么?
为什么上面的refspec是必要的 - 它做了什么?
答案 0 :(得分:47)
refspec告诉git如何将远程引用映射到本地仓库。
您列出的值为+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
。默认情况下,它不允许这样做,因为它不是快进(它会告诉你它拒绝了该参考的拉动),但因为规则以+
开头,它会接受它。
A --- B <--(master)
\
C <--(origin/master)
(在这种情况下,拉动会导致合并提交。)
第二种模式类似,但对于merge-requests
参考(我认为这与您的服务器实施PR相关;我不熟悉它)。< / p>
有关refspecs的更多信息:https://git-scm.com/book/en/v2/Git-Internals-The-Refspec
答案 1 :(得分:1)
refspec告诉git如何将引用从远程映射到本地仓库。
在Git 2.29(2020年第四季度)中,refspec还可以告诉Git对 exclude 的引用。
“ 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
请参见commit c0192df的Jacob Keller (jacob-keller
)(2020年9月30日)。
(由Junio C Hamano -- gitster
--在commit 8e3ec76中合并,2020年10月5日)
refspec
:添加对否定引用规格的支持签名人:Jacob Keller
fetch
和push
都支持模式refspec,它们允许获取或推送与特定模式匹配的参考。
由于这些模式是问题,因此它们在表达更复杂情况时的能力有限。例如,假设您希望从远程获取所有分支,但特定分支除外。为此,必须设置一组仅与所需分支匹配的refspec。
由于refspec是显式名称匹配或简单的全局变量,因此无法表达许多模式。添加对新类型的refspec(称为“负” refspecs)的支持。
这些前缀以'
^
'开头,意思是“exclude any ref matching this refspec
”。
他们只能有一个总是指来源的“方面”。
- 在获取期间,这是指远程服务器上的引用的名称。
- 在推送过程中,这是指本地端引用的名称。
使用否定的参考规范,用户可以表达更复杂的模式。对于 例如:
git fetch origin refs/heads/*:refs/remotes/origin/* ^refs/heads/dontwant
会将
origin
上的所有分支提取到remotes/origin
中,但将排除 提取名为dontwant
的分支。今天的参考规格是可互换的,这意味着顺序并不重要。
而不是强制隐含的顺序,否定的refspec将始终最后应用。
也就是说,为了匹配,一个引用必须匹配至少一个正引用规范,并且不匹配任何一个负引用规范。
这类似于否定路径规范的工作方式。
The documentation现在包括:
<refspec>
的{{1}}中可能包含*
,以指示简单的模式 匹配。
此类refspec的功能类似于与任何具有相同前缀的ref匹配的glob。模式<src>
的{{1}}和{<refspec>
。通过将*
替换为{ 内容与来源匹配。如果refspec以
<src>
为前缀,则它将被解释为否定 refspec 。
这样的refspec不会指定要获取的引用或要更新的本地引用,而是会指定要排除的引用。
如果一个参考至少匹配一个正参考规范,但不匹配任何负参考规范,则视为匹配。负引用规范可用于限制模式refspec的范围,以使其不包括特定引用。
负refspec本身可以是模式refspec。但是,他们可能只会 包含<dst>
并且不指定*
。
充分说明了十六进制对象 名称也不被支持。
有关更多示例,请参见t5582-fetch-negative-refspec.sh