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

但您甚至可以选择性地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) 的 commit c0192df(2020 年 9 月 30 日)。(由 Junio C Hamano -- gitster -- 合并到 commit 8e3ec76,2020 年 10 月 5 日)

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

签字人:Jacob Keller

fetchpush 都支持模式引用规范,允许获取或推送与特定模式匹配的引用。 因为这些模式是全局的,所以它们表达更复杂情况的能力有限。

例如,假设您希望从远程获取除特定分支之外的所有分支。为此,您必须设置一组仅匹配所需分支的 refspec。 因为 refspecs 要么是显式名称匹配,要么是简单的 glob,因此许多模式无法表达。

添加对新型 refspec 的支持,称为“否定”refspecs

它们以“^”为前缀,意思是“exclude any ref matching this refspec”。 它们只能有一个始终指向源的“侧面”。

在获取期间,这指的是遥控器上 ref 的名称。 在推送期间,this 指的是本地端的 ref 名称。

使用否定的 refspec,用户可以表达更复杂的模式。为了 示例:

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

会将origin 上的所有分支提取到remotes/origin,但会排除 获取名为 dontwant 的分支。

今天的参考规范是可交换的,这意味着顺序并不重要。 否定的 refspecs 总是最后应用,而不是强制一个隐含的顺序。 也就是说,为了匹配,一个 ref 必须至少匹配一个正 refspec,并且不匹配任何负 refspec。 这类似于负路径规范的工作方式。


The documentation 现在包括:

&lt;refspec&gt; 可能在其&lt;src&gt; 中包含* 以指示简单模式 匹配。 这样的 refspec 的功能类似于匹配任何具有相同前缀的 ref 的 glob。模式 &lt;refspec&gt; 必须在 &lt;src&gt;&lt;dst&gt;。它将通过将* 替换为 内容与源匹配。

如果 refspec 以 ^ 为前缀,它将被解释为否定 参考规范。 这样的 refspec 将改为指定要排除的 refs,而不是指定要获取哪些 refs 或要更新哪些本地 refs。 如果一个 ref 至少匹配一个正 refspec,并且不匹配任何负 refspec,则该 ref 将被视为匹配。

负引用规范可用于限制模式引用规范的范围,使其不包含特定引用。 负引用规范本身可以是模式引用规范。然而,他们可能只 包含&lt;src&gt;,但不指定&lt;dst&gt;。 完全拼出的十六进制对象 也不支持名称。

更多示例请参见t5582-fetch-negative-refspec.sh

【讨论】:

对于那些只有本地手册页(v2.31 版本)的人,文档将位于 git help pullgit 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.

git push 错误:src refspec main 与 linux 上的任何内容都不匹配