Git -什么是“Refspec”

rjee0c15  于 2022-12-17  发布在  Git
关注(0)|答案(2)|浏览(212)

我一直遵循this guide来配置GitLab与Jenkins的持续集成。
作为该过程的一部分,有必要按如下方式设置refspec:+refs/heads/*:refs/remotes/origin/* +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*
为什么这是必要的,并没有解释在后,所以我开始在网上寻找一个解释,并期待在official documentation以及一些相关的StackOverflow问题like this one
尽管如此,我还是很困惑:

**refspec到底是什么?**为什么上面的refspec是必要的-它做什么?

vyu0f0g1

vyu0f0g11#

refspec告诉git如何将引用从远程库Map到本地库。
您列出的值为+refs/heads/*:refs/remotes/origin/* +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*;让我们来分析一下。
你有两个图案,它们之间有一个空间;这意味着你要给出多个规则(progit书中称之为两个refspecs;这在技术上可能更正确。但是,如果需要的话,你几乎总是有能力列出多个参考规范,所以在日常生活中,这可能没有什么区别。)
那么,第一模式是+refs/heads/*:refs/remotes/origin/*,其具有三个部分:

  1. +意味着应用规则而不会失败,即使这样做会以非快进的方式移动目标引用。
  2. :之前的部分(如果有+,则在+之后)是“source”模式,即refs/heads/*,这意味着该规则适用于refs/heads下的任何远程引用(即分支)。
  3. :后面的部分是“destination”模式,即refs/remotes/origin/*
    因此,如果原点有一个分支master,表示为refs/heads/master,这将创建一个远程分支引用origin/master,表示为refs/remotes/origin/master,对于任何分支名称(*)都是如此。
    回到+假设原点有
A --- B <--(master)

获取和,应用得到的refspec

A --- B <--(origin/master)

(If您应用了典型的跟踪规则并执行了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 refs(我认为这与服务器的PR实现有关;我不太熟悉)。
有关参照规范的详细信息:https://git-scm.com/book/en/v2/Git-Internals-The-Refspec

pwuypxnk

pwuypxnk2#

refspec告诉git如何将引用从远程库Map到本地库。
在Git 2.29(Q4 2020)中,refspec还可以告诉Git哪些引用需要 exclude.git fetch“和“git push“支持负refspec。
因此,您不仅可以选择性地使用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

参见Jacob Keller ( jacob-keller )(2020年9月30日)。
(由Junio C Hamano -- gitster --合并到commit 8e3ec76,2020年10月5日)

refspec:添加对负参照规范的支持

签署人:雅各布·凯勒
fetchpush都支持模式引用规范,允许获取或推送与特定模式匹配的引用。因为这些模式是全局对象,所以它们在表达更复杂的情况时能力有限。
例如,假设你想从一个远程数据库中获取除特定分支之外的所有分支。要实现这一点,你必须设置一组只匹配你想要的分支的引用规范。因为引用规范要么是显式的名称匹配,要么是简单的全局对象,所以许多模式无法表达。

添加对一种新类型参照规范的支持,称为“负”参照规范

这些引用以“^”为前缀,表示“排除与此引用规范匹配的任何引用”。
它们只能有一个“面”,这个面总是指来源。

  • 在获取过程中,这将引用远程数据库上的ref的名称。
  • 在推送过程中,它引用本地端的ref的名称。

使用负refspecs,用户可以表达更复杂的模式。例如:

git fetch origin refs/heads/*:refs/remotes/origin/* ^refs/heads/dontwant

origin上的所有分支都读入remotes/origin,但不读入名为dontwant的分支。
现在的Refspecs是可交换的,这意味着顺序并不明显重要。负的refspecs将总是最后应用,而不是强制一个隐含的顺序。也就是说,为了匹配,一个ref必须匹配至少一个正的refspecs,并且不匹配任何负的refspecs。这与负的路径规范的工作原理类似。
文档现在包括:
<refspec>可以在其<src>中包含*以指示简单的模式匹配。这样的refspec的功能类似于匹配具有相同前缀的任何ref的glob。模式<refspec>必须在<src><dst>中都有*。它会将引用Map到目标,方法是用源中匹配的内容替换*

如果引用规范以^为前缀,则会被解释为负引用规范。这样的引用规范将指定要排除的引用,而不是指定要获取的引用或要更新的本地引用。如果引用与至少一个正引用规范匹配,并且不与任何负引用规范匹配,则认为该引用匹配。

负引用规范可以用来限制模式引用规范的范围,使其不包括特定的引用。负引用规范本身可以是模式引用规范。但是,它们可能只包含<src>而不指定<dst>。也不支持完整拼写的十六进制对象名称。
有关更多示例,请参见t5582-fetch-negative-refspec.sh

相关问题