Git - 什么是" Refspec"

时间:2017-06-02 16:22:31

标签: git jenkins gitlab git-refspec

我一直关注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是必要的 - 它做了什么?

2 个答案:

答案 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/masterB移动到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*

但是您甚至可以选择pushpush --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 c0192dfJacob Keller (jacob-keller)(2020年9月30日)。 (由Junio C Hamano -- gitster --commit 8e3ec76中合并,2020年10月5日)

refspec:添加对否定引用规格的支持

签名人:Jacob Keller

fetchpush都支持模式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