5

我正在获取远程分支并陷入某种循环。

我取一次并得到:

$ git fetch
* [new branch]      minorRelease/something-> origin/minorRelease/something

然后我再次获取并得到:

$ git fetch
* [new branch]      minorRelease/Something-> origin/minorRelease/Something

同一个分支,但有一个大写字母S

我试图从以下文件夹中删除文件.git/refs/remotes/origin/minorRelease,但是当再次获取时,我得到了两者并返回到上面的循环:

$ git fetch
* [new branch]      minorRelease/Something-> origin/minorRelease/Something
* [new branch]      minorRelease/something-> origin/minorRelease/something
4

2 回答 2

8

@torek是的,它是由 和 的差异引起LinuxWindowsLinux是区分大小写的,而Windows不是。您可以使用ls-remote来显示服务器中的分支。

git ls-remote --heads origin

而且我认为在你的情况下,输出应该包括两个分支,只有S不同的情况。

ref/heads/minorRelease/Something
ref/heads/minorRelease/something

如果您发现其中一个实际上是重复的,您可以删除远程分支。然后再做fetch一次。现在应该没问题了。

git push origin :minorRelease/Something
git fetch
于 2014-09-29T05:56:13.403 回答
2

注意:使用 Git 2.12(2017 年第一季度)这将变得更容易发现,因为您可以使用不区分大小写的选项列出分支。

请参阅Nguyễn Thái Ngọc Duy ( )的提交 3bb16a8(2016 年 12 月 4 日) 。(由Junio C Hamano 合并——提交 73e494f中,2016 年 12 月 19 日)pclouds
gitster

tag, branch, for-each-ref: 添加--ignore-case用于排序和过滤。
此选项使排序忽略大小写,当您有名为 的分支bug-12-do-somethingBug-12-do-some-more希望 BUG-12-do-what将它们组合在一起时,这非常有用。
外部排序可能不是一种选择,因为我们从 git-branch 和 git-tag 中丢失了颜色和列布局。

过滤也可以这样说,但它可能不太重要,因为[bB][uU][gG]-*如果你绝望,你总是可以使用丑陋的模式。

但是,您不能进行区分大小写的过滤和不区分大小写的排序(或相反)。对于branchtag,应该没问题。for-each-ref,作为管道,可能需要更好的控制。
但是我们总是可以--{filter,sort}-ignore-case在需要时添加它。

git branch --ignore-case --list

注意:--ignore-case“”(及其朋友)的“”选项git for-each-ref无法正常工作,已在 Git 2.19(2018 年第三季度)中修复。

请参阅Aleksandr Makarov ( ) 的提交 639ab5e(2018 年 7 月 2 日。 请参阅Jeff King ( ) 的commit e674eb2commit ee0f3e2(2018 年 7 月 2 日(由Junio C Hamano 合并 -- --提交 4301330中,2018 年 7 月 24 日)deviance
peff
gitster

ref-filter: 避免后端过滤--ignore-case

for-each-ref与 一起使用时--ignore-case,我们希望match_name_as_path()进行不区分大小写的匹配。
但是在我们到达那里之前,就会发生额外的过滤层。由于提交 cfe004a ( ref-filter: limit traversal to prefix, 2017-05-22, Git v2.14.0),我们将前缀提供给 ref 后端,以便它可以优化 ref 迭代。

我们没有机制告诉后端我们不区分大小写匹配。短期内也不可能有一个,因为打包的后端依赖于对已排序的 refs 列表进行二进制搜索。
让我们简单地讨论一下这个案子。额外的过滤是我们根本做不到的优化。我们仍然会通过match_name_as_path() 中的过滤给出正确答案。


请注意,在 Git 2.23(2019 年第三季度)中,git for-each-ref具有多种模式的 " " 已得到优化。

请参阅Taylor Blau ( ) 的提交 b31e268(2019 年 6 月 26 日(由Junio C Hamano 合并 -- --提交 b4b8c35中,2019 年 7 月 19 日)ttaylorr
gitster

ref-filter.c: 查找不相交的模式前缀

cfe004a ( ref-filter: limit traversal to prefix, 2017-05-22, Git v2.14.0-rc0) 以来,ref-filter代码一直试图将遍历限制为给定模式的前缀。

该代码没有处理多个模式,因为这意味着多次调用“for_each_ref_in”。
如果我们不注意哪些模式重叠,我们将多次输出相同的参考。

例如,考虑模式集“refs/heads/a/*”、“refs/heads/a/b/c”和“refs/tags/v1.0.0”。如果我们天真地跑:

  for_each_ref_in("refs/heads/a/*", ...);
  for_each_ref_in("refs/heads/a/b/c", ...);
  for_each_ref_in("refs/tags/v1.0.0", ...);

我们会看到 ' refs/heads/a/b/c' (以及它下面的所有内容)两次。

相反,我们希望将模式划分为不相交的集合,我们知道不同集合中的任何两个模式都不会匹配任何 ref。
在上面,这些是:

  • {'refs/heads/a/*', 'refs/heads/a/b/c'}, 和
  • {'refs/tags/v1.0.0'}

给定这些不相交的集合之一,传递给“ for_each_ref_in”的合适模式是什么?

一种方法是计算该不相交集中所有元素的最长公共前缀,并让调用者剔除他们不想要的引用。
计算最长前缀意味着在大多数情况下,我们不会匹配调用者想要忽略的太多东西。

上述最长的公共前缀是:

  • {'refs/heads/a/*', 'refs/heads/a/b/c'} -> refs/heads/a/*
  • {'refs/tags/v1.0.0'} -> refs/tags/v1.0.0

我们改为调用:

  for_each_ref_in("refs/heads/a/*", ...);
  for_each_ref_in("refs/tags/v1.0.0", ...);

这为我们提供了我们正在寻找的 refs 以及最少量的额外内容,但绝不会与我们要求的 ref 重复。

这里实现的是完成上述操作的算法,其工作原理如下:

  1. 按字典顺序对给定的模式列表进行排序。

  2. 将 'prefix' 初始化为空字符串,我们的目标是在上述最长公共前缀集中构建每个元素。

  3. 考虑给定集中的每个模式,如果它到达模式的末尾或触及通配符,则发出“前缀”。字符串的结尾被视为在通配符之前。(请注意,未来的工作还有一些空间来检测,例如,'a?b' 和 'abc' 是不相交的)。

  4. 否则,(3)使用对应于我们当前前缀的列表切片(即,将我们的前缀作为文字字符串前缀的模式子集)逐步递归。

这个算法是' O(kn + n log(n))',其中' k'max(len(pattern))代表列表中的每个模式,' n'是len(patterns)

通过发现这组有趣的模式,我们将多模式“ git for-each-ref”(和其他引用遍历)的运行时间从 减少O(N)O(n log(N)),其中“ N”是打包引用的总数。

在 'refs/tags/huge-N' 中有 10,000,000 个 refs 的存储库上运行 'git for-each-ref refs/tags/a refs/tags/b',我最好的五次来自:

  real    0m5.805s
  user    0m5.188s
  sys     0m0.468s

至:

  real    0m0.001s
  user    0m0.000s
  sys     0m0.000s

在 上linux.git,挖掘两个最新-rc标签的时间从 0.002 秒下降到 0.001 秒,因此标签较少的存储库的变化不太明显。


" git branch" 和其他 " " 变体按优先级递增的顺序for-each-ref接受多个选项,但它在 " " 处理和与 refname 的平局中存在一些问题,这些问题已在 Git 2.27(2020 年第二季度)中得到修复。--sort=<key>--ignore-case

请参阅Jeff King ( ) 的提交 7c5045f提交 76f9e56(2020 年 5 月 3 日(由Junio C Hamano 合并 -- --提交 6de1630中,2020 年 5 月 8 日)peff
gitster

ref-filter: 适用--ignore-case所有排序键

签字人:杰夫·金

所有ref-filter用户(for-each-refbranchtag)都有一个--ignore-case选项,使过滤和排序不区分大小写。

但是,此选项仅应用于ref_sortinglist的第一个元素。

所以:

git for-each-ref --ignore-case --sort=refname

会做你所期望的,但是:

git for-each-ref --ignore-case --sort=refname --sort=taggername

将对主键(标记名)进行不区分大小写的排序,但对引用名进行区分大小写的排序。我们在这里有两个选择:

  • 教调用者在整个列表上设置 ignore_case

  • 将 ref_sorting 列表替换为包含排序键列表以及适用于所有键的选项的结构

我在这里选择了第一个,因为如果我们以后想让用户为每个键设置标志,它会提供更大的灵活性(可能在定义键时通过一些特殊的语法;现在它是 all or nothing through --ignore-case)。

新的测试通过不区分大小写对标记器和主题进行排序来涵盖这一点,它应该对“ a”和“ A”进行相同的比较,但仍将它们排序在“ b”和“ B”之前。
我们将通过对 refname 进行排序来打破平局,给自己一个稳定的输出(这实际上应该是自动完成的,但还有另一个错误将在下一次提交中修复)。

于 2016-12-23T20:30:43.757 回答