【问题标题】:Is it possible to use filters in refspec in places other than directory namespaces?是否可以在目录命名空间以外的地方使用 refspec 中的过滤器?
【发布时间】:2013-12-25 08:17:03
【问题描述】:

查看this 的示例显示 refspecs 可以过滤目录/命名空间,如下所示:

+refs/heads/qa/*:refs/remotes/origin/qa/*

但是,我正在尝试优化 fetch 并且我正在使用的 repo 具有这样命名的分支: release-6.0.0 当尝试过滤这些时,我得到:

fatal: Invalid refspec '+refs/heads/release*:refs/remotes/upstream/release*' 有什么方法可以在 fetch 中过滤这些,还是我需要获取所有远程头?

【问题讨论】:

  • 有趣。在 git 的其他地方,可以使用 glob 样式匹配(即使在 refs 上,例如使用 git for-each-ref),所以我不确定为什么这不起作用。
  • 是的,我尝试在其中使用的同一脚本有:git for-each-ref --sort='-*authordate' --format '%(refname:short)' refs/remotes/origin/release*" 所以当上述失败时我很惊讶。
  • 我也试过 +refs/heads/release*:refs/remotes/upstream/* 认为客户端需要成为一个目录可能是有意义的,但也失败了。
  • 注意:这在 git 2.6 中应该是可能的。见my edited answer below

标签: git


【解决方案1】:

Git 2.6+(2015 年第三季度)将允许这种 refspec!

参见commit cd377f4commit 53a8555(2015 年 7 月 22 日)Jacob Keller (jacob-keller)
(由 Junio C Hamano -- gitster -- 合并于 commit 8d3981c,2015 年 8 月 3 日)

refs:放宽对通配符“*”参考规范的限制

通过允许在组件中包含“*”而不是仅作为整个组件的模式来放宽对 refspecs 的限制。

check_refname_format() 中删除接受单个“*”作为整个组件的逻辑,并在 check_refname_component() 中实现该逻辑的扩展形式。
将指向 flags 参数的指针传递给后者,因为它必须在看到“*”时清除 REFNAME_REFSPEC_PATTERN 位。

教导check_refname_component() 函数仅在标志中设置REFNAME_REFSPEC_PATTERN 时允许星号“*”,并在看到“*”后丢弃该位,以确保 refspec 的一侧最多包含一个星号。

这将使我们能够接受参考规范,例如for/bar*:foo/baz*
之前运行的任何 refspec 都应继续使用新逻辑运行。


原始答案(2013 年)

这似乎不可能,因为这种限制有助于remote.c 完成的引用匹配。

这可以追溯到 Git 1.5.6.5(2008 年 8 月)和 commit b2a5627 (Daniel Barkalow),它们强制执行“通配符 refspec 必须以斜杠和星号结尾”的规则:

通配符 refspec 在内部被解析为带有 srcdst 字符串的 refspec 结构。
当将通配符模式与我们在远程看到的实际引用匹配时,代码的许多部分假定这些不包括尾随的“/*”。
这意味着我们不仅需要确保前缀匹配,而且还要确保匹配的部分后面有一个斜线。

但是从ls-remote 扫描结果并找到匹配引用的代码路径忘记检查“匹配部分必须后跟斜杠”规则。
这导致来自远程端的“refs/heads/b1”错误地匹配“refs/heads/b/*:refs/remotes/b/*”refspec 的源端。

更糟糕的是,由“git-clone”内部制作的 refspec 以及用于实现“git-fetch --tags”的硬编码预解析 refspec 违反了“解析的widcard refspec 不以斜线结尾”规则;只需添加“匹配部分必须后跟斜杠”规则,就会破坏使用这些 refspecs 的代码路径。

此提交将规则更改为需要尾部斜杠来解析通配符 refspec。
IOW,“refs/heads/b/*:refs/remotes/b/*”被解析为src = "refs/heads/b/"dst = "refs/remotes/b/"
这让我们可以简化匹配逻辑,因为我们只需要做一个prefixcmp() 即可 注意“refs/heads/b/one”匹配而“refs/heads/b1”不匹配。


OP Monte Goulding 指出 commit 46220ca (diff) 是此规则的起源(Git 1.5.5,2007 年 4 月)

根据我的建议,我们在较早的 commit ef00d15(Tighten refspec 处理,2008-03-17)中收紧了 refspec 验证代码,但该建议一开始就被误导了,它破坏了这种用法:

$ git push origin HEAD~12:master

push refspecs 和 fetch refspecs 的语法相似,它们都是用冒号分隔的 LHS 和 RHS(可能以 + 为前缀强制),但相似之处到此为止。
例如,push refspec 中的 LHS 可以是在运行时计算为有效对象名称的任何内容(除非冒号和 RHS 丢失,或者它是一个 glob),而它必须是 fetch refspec 中看起来有效的 refname。
为了正确验证它们,调用者需要能够说出它们是哪种类型的 refspec。
保留一个无法判断它在处理哪种类型的接口,并要求它表现得明智是不合理的。

此提交将两者的解析分离为不同的函数,并澄清代码以实现正确的解析(即分成两部分,确保两边都是通配符或两边都不是)。

【讨论】:

  • 嗯...我不确定我明白了。如果 refspec 是 refs/heads/b/* 你希望它匹配 refs/heads/b/one 但不是 refs/heads/b1 但如果它是 refs/heads/b* 你希望它匹配 refs/heads/b1 和不是 refs/heads/b/one。如果您的 refspec 是 refs/heads/b*,我只能对两者匹配进行成像,但在这种情况下,您应该为两者做好准备......
  • 查看提交在我看来,如果它被修改为在检查格式之前只删除并放回尾部斜杠,如果尾部斜杠存在,它将启用我想要做的事情并且仍然保护带有斜杠的 refspecs 不会返回错误的结果。这种变化会有什么缺点?
  • @MonteGoulding 我同意,这似乎是可行的。它必须针对所有其他 Git 单元测试进行测试
  • 您知道“匹配部分必须后跟斜线”规则是否有更多历史记录?
  • @MonteGoulding 不是我知道的,当我探索remote.c的历史时
猜你喜欢
  • 1970-01-01
  • 2020-07-20
  • 1970-01-01
  • 1970-01-01
  • 2016-02-24
  • 2013-06-10
  • 1970-01-01
  • 2010-10-06
  • 1970-01-01
相关资源
最近更新 更多