【问题标题】:Git sparse checkout with exclusion带排除的 Git 稀疏结帐
【发布时间】:2012-03-23 06:21:24
【问题描述】:

根据this thread,应该实现Git 的sparse-checkout feature 中的排除。是吗?

假设我有以下结构:

papers/
papers/...
presentations/
presentations/heavy_presentation
presentations/...

现在我想从结帐中排除presentations/heavy_presentation,而将其余部分留在结帐中。我还没有设法让它运行。什么是正确的语法?

【问题讨论】:

    标签: git sparse-checkout


    【解决方案1】:

    遗憾的是,上述方法都不适合我,所以我花了很长时间尝试sparse-checkout 文件的不同组合。

    就我而言,我想跳过带有 IntelliJ IDEA 配置的文件夹。

    这是我所做的:


    运行git clone https://github.com/myaccount/myrepo.git --no-checkout

    运行git config core.sparsecheckout true

    创建.git\info\sparse-checkout,内容如下

    !.idea/*
    !.idea_modules/*
    /*
    

    运行 'git checkout --' 以获取所有文件。


    使其工作的关键是在文件夹名称后添加/*

    我有 git 1.9

    【讨论】:

      【解决方案2】:

      我本来希望像下面这样的东西可以工作:

      /*
      !presentations/heavy_presentation
      

      但事实并非如此。我确实尝试了许多其他组合。我认为排除没有正确实施,并且周围存在错误(仍然)

      类似:

      presentations/*
      !presentations/heavy_presentation
      

      确实有效,您将获得没有heavy_presentation文件夹的演示文件夹。

      因此,解决方法是明确包含其他所有内容。

      【讨论】:

      • 谢谢,已确认。我已编辑您的帖子以添加另一个不起作用的示例。
      • 您的第一个解决方案在 Windows 上的 git 2.21.0 中为我工作
      【解决方案3】:

      在 Git 2.25(2020 年第一季度)中,稀疏签出工作树的管理获得了专用的"sparse-checkout" command

      首先,这是一个扩展示例,以fast clone using a --filter option 开头:

      git clone --filter=blob:none --no-checkout https://github.com/git/git
      cd git
      git sparse-checkout init --cone
      # that sets git config core.sparseCheckoutCone true
      git read-tree -mu HEAD
      

      使用锥形选项(详细/记录如下)意味着您的 .git\info\sparse-checkout 将包含以下开头的模式:

      /*
      !/*/
      

      含义:只有顶级文件,没有子文件夹。
      如果你不想要top file,你需要避免圆锥模式:

      # Disablecone mode in .git/config.worktree
      git config core.sparseCheckoutCone false
      
      # remove .git\info\sparse-checkout
      git sparse-checkout disable
      
      # Add the expected pattern, to include just a subfolder without top files:
      git sparse-checkout set /mySubFolder/
      
      # populate working-tree with only the right files:
      git read-tree -mu HEAD
      

      详细说明:

      (在“Bring your monorepo down to size with sparse-checkout”查看更多信息,来自 Derrick Stolee)

      因此,不仅排除子文件夹确实有效,而且在稀疏结帐的“锥形”模式下(使用 Git 2.25)会更快工作。

      commit 761e3d2(2019 年 12 月 20 日)Ed Maste (emaste)
      commit 190a65f(2019 年 12 月 13 日),commit cff4e91commit 416adc8commit f75a69fcommit fb10ca5commit 99dfa6fcommit e091228commit e9de487commit eb42fec,@9876543336@,@987654 ,commit 96cc8abcommit 879321ecommit 72918c1commit 7bffca9commit f6039a9commit d89f09ccommit bab3c35commit 94c0956(2019 年 11 月 21 日)Derrick Stolee (derrickstolee)
      请参阅 Jeff Hostetler (Jeff-Hostetler)commit e6152e3(2019 年 11 月 21 日)。
      (由 Junio C Hamano -- gitster -- 合并于 commit bd72a08,2019 年 12 月 25 日)

      sparse-checkout: 添加“锥形”模式

      签字人:Derrick Stolee

      随着索引中的模式数量和条目数量的增长,稀疏结帐功能可以具有二次性能。
      如果有 1,000 个模式和 1,000,000 个条目,那么这个时间可能非常重要。

      创建一个新的布尔配置选项 core.sparseCheckoutCone,以表明我们希望稀疏结帐文件包含一组更有限的模式。
      这是与core.sparseCheckout 分开的配置设置,以避免通过引入三态选项来破坏旧客户端。

      config man page 包括:

      `core.sparseCheckoutCone`:
      

      启用稀疏结帐功能的“锥形模式”。
      当 sparse-checkout 文件包含一组有限的模式时,这种模式提供了显着的性能优势。

      git sparse-checkout man page 详情:

      锥形图案集

      完整的模式集允许任意模式匹配和复杂的包含/排除规则。
      这些可能导致更新索引时O(N*M) 模式匹配,其中N 是模式数,M 是索引中的路径数。为了解决这个性能问题,启用core.spareCheckoutCone 时允许使用更受限制的模式集。

      圆锥模式集中接受的模式是:

      1. 递归:目录内的所有路径都包括在内。
      2. 父级: 直接位于目录中的所有文件都包括在内。

      除了以上两种模式,我们还期望根目录下的所有文件都包含在内。如果添加递归模式,则所有前导目录都将添加为父模式。

      默认情况下,在运行git sparse-checkout init 时,会添加根目录作为父模式。 此时,sparse-checkout 文件包含以下模式:

      /*
      !/*/
      

      这表示“包含根目录中的所有内容,但根目录以下两级不包含任何内容。”
      如果我们随后将文件夹 A/B/C 添加为递归模式,则文件夹 AA/B 将添加为父模式。
      生成的 sparse-checkout 文件现在是

      /*
      !/*/
      /A/
      !/A/*/
      /A/B/
      !/A/B/*/
      /A/B/C/
      

      在这里,顺序很重要,因此负面模式会被正面模式覆盖 在文件中显示在较低位置的模式。

      如果是core.sparseCheckoutCone=true,则 Git 将解析预期这些类型的模式的 sparse-checkout 文件。
      如果模式不匹配,Git 会发出警告。
      如果模式确实匹配预期的格式,那么 Git 将使用更快的哈希 - 基于算法来计算 sparse-checkout 中的包含。

      所以:

      sparse-checkout: 初始化并设置为锥形模式

      协助人:Eric Wong
      协助人:Johannes Schindelin
      签字人:Derrick Stolee

      为了使锥形模式集易于使用,请更新“git sparse-checkout (init|set)”的行为。

      将“--cone”标志添加到“git sparse-checkout init”以设置配置选项“core.sparseCheckoutCone=true”。

      在锥形模式下运行“git sparse-checkout set”时,用户只需提供递归文件夹匹配列表。 Git 会自动为前导目录添加必要的父匹配项。


      请注意,--cone 选项仅记录在 Git 2.26(2020 年第一季度)
      (由 Junio C Hamano -- gitster -- 合并到 commit ea46d90,2020 年 2 月 5 日)

      docsparse-checkout:提到--cone选项

      签字人:Matheus Tavares
      签字人:Derrick Stolee

      af09ce2 ("sparse-checkout: init and set in cone mode", 2019-11-21, Git v2.25.0-rc0 -- merge) 中,添加了 '--cone' 选项'git sparse-checkoutinit'。

      记录在git sparse-checkout:

      这包括:

      当提供--cone 时,core.sparseCheckoutCone 设置也被设置,允许在有限的一组模式下获得更好的性能。

      (上面显示的“模式集”,在此答案的“CONE PATTERN SET”部分)


      这种新的“锥形”模式会快多少?

      sparse-checkout: 使用 hashmaps 表示圆锥模式

      协助人:Eric Wong
      协助人:Johannes Schindelin
      签字人:Derrick Stolee

      sparse-checkout 中“锥形模式”选项允许的父模式和递归模式具有足够的限制性,我们可以避免使用正则表达式解析。一切都基于前缀匹配,因此我们可以使用哈希集来存储稀疏签出文件中的前缀。在检查路径时,我们可以从路径中剥离路径条目并检查哈希集是否完全匹配。

      作为测试,我为 Linux 存储库创建了一个锥形模式稀疏签出文件,该文件实际上包含每个文件。这是通过获取 Linux 存储库中的每个文件夹并在此处创建模式对来构建的:

      /$folder/
      !/$folder/*/
      

      这导致了 8,296 个模式的稀疏签出文件。
      在这个文件上运行 'git read-tree -mu HEAD' 有以下性能:

          core.sparseCheckout=false: 0.21 s (0.00 s)
          core.sparseCheckout=true : 3.75 s (3.50 s)
      core.sparseCheckoutCone=true : 0.23 s (0.01 s)
      

      根据trace2 性能跟踪,上面括号中的时间对应于第一次clear_ce_flags() 调用所花费的时间。

      虽然此示例是人为设计的,但它演示了这些模式如何减慢稀疏结帐功能。

      还有:

      sparse-checkout: 在锥形模式下尊重 core.ignoreCase

      签字人:Derrick Stolee

      当用户在锥形模式下使用稀疏检出功能时,他们使用“git sparse-checkout set <dir1> <dir2> ...”或使用“--stdin”添加模式,以通过标准输入逐行提供目录。
      这种行为自然看起来很像用户输入“git add <dir1> <dir2> ...”的方式

      如果启用了core.ignoreCase,则“git add”将使用不区分大小写的匹配来匹配输入。
      sparse-checkout 功能执行相同操作。

      unpack_trees() 期间更新跳过工作树位时执行不区分大小写的检查。这是通过将哈希算法和哈希图比较方法更改为可选地使用不区分大小写的方法来完成的。

      启用此选项后,散列算法的性能成本会很小。
      为了找出最坏的情况,以下是在具有深层目录结构的 repo 上运行的:

      git ls-tree -d -r --name-only HEAD |
      git sparse-checkout set --stdin
      

      “设置”命令在 core.ignoreCase 禁用或启用的情况下进行计时。
      对于历史悠久的回购,数字是

      core.ignoreCase=false: 62s
      core.ignoreCase=true:  74s (+19.3%)
      

      为了重现性,Linux 内核存储库上的等效测试具有以下数字:

      core.ignoreCase=false: 3.1s
      core.ignoreCase=true:  3.6s (+16%)
      

      现在,这并不是一个完全公平的比较,因为大多数用户将使用更浅的目录来定义他们的稀疏锥体,以及 eb42feca97 的性能改进(“unpack-trees: hash less in cone mode”2019-11- 21、Git 2.25-rc0) 可以去除大部分的哈希开销。要进行更实际的测试,请从 ls-tree 命令中删除“-r”以仅存储第一级目录。
      在这种情况下,Linux 内核存储库在每种情况下都需要 0.2-0.25 秒,而深层存储库在每种情况下都需要 1 秒,正负 0.05 秒。

      因此,我们可以证明此更改的成本,但这对任何合理的稀疏结帐锥都不太重要。


      在 Git 2.25(2020 年第一季度)中,“git sparse-checkout list”子命令学会了在“锥形”模式生效时以更简洁的形式给出其输出。

      参见Derrick Stolee (derrickstolee)commit 4fd683bcommit de11951(2019 年 12 月 30 日)。
      (由 Junio C Hamano -- gitster -- 合并到 commit c20d4fd,2020 年 1 月 6 日)

      sparse-checkout: 以锥形模式列出目录

      签字人:Derrick Stolee

      启用core.sparseCheckoutCone 时,“git sparse-checkout set”命令将目录列表作为输入,然后创建稀疏签出模式的有序列表,以便递归包含这些目录以及父目录中的所有同级条目也包括在内。
      列出模式不如目录本身那么用户友好。

      在锥形模式下,只要模式与预期的锥形模式类型匹配,将“git sparse-checkout list”的输出更改为仅显示创建模式的目录。

      通过此更改,以下管道命令不会更改工作目录:

      git sparse-checkout list | git sparse-checkout set --stdin
      

      这唯一不起作用的情况是core.sparseCheckoutConetrue,但稀疏检出文件包含与锥形模式的预期模式类型不匹配的模式。


      最近在此版本中添加的代码以稀疏圆锥模式移动到索引中同一目录中的条目之外的条目,没有计算错误跳过的条目数,已通过 Git 更正2.25.1(2020 年 2 月)。

      Junio C Hamano (gitster)commit 7210ca4(2020 年 1 月 27 日)。
      请参阅 Derrick Stolee via GitGitGadget (``)commit 4c6c797(2020 年 1 月 10 日)。
      (由 Junio C Hamano -- gitster -- 合并于 commit 043426c,2020 年 1 月 30 日)

      unpack-trees:正确计算结果计数

      报告人:Johannes Schindelin
      签字人:Derrick Stolee

      clear_ce_flags_dir() 方法处理公共目录中的缓存条目。返回的int 是该目录处理的缓存条目数。
      在锥形模式下使用稀疏签出功能时,我们可以跳过完全包含或完全排除目录中的条目的模式匹配。

      eb42feca ("unpack-trees: hashless in cone mode", 2019-11-21, Git v2.25.0-rc0 -- merge 列在batch #0) 引入了这个性能特性。旧机制依赖于调用clear_ce_flags_1() 返回的计数,但新机制通过从“cache”中减去“cache_end”来计算行数,以找到范围的大小。
      然而,等式是错误的,因为它除以sizeof(struct cache_entry *)。这不是指针运算的工作原理!

      为 2.25.0 版本准备的适用于 Windows 的 Git 的覆盖构建发现此问题并带有警告:

      Pointer differences, such as `cache_end` - cache, are automatically 
      scaled down by the size (8 bytes) of the pointed-to type (struct `cache_entry` *). 
      Most likely, the division by sizeof(struct `cache_entry` *) is extraneous 
      and should be eliminated.
      

      这个警告是正确的。

      这给我们留下了一个问题:“这甚至是如何工作的?”

      这种不正确的指针算法出现的问题是一个性能错误,而且是一个非常轻微的错误。
      由于clear_ce_flags_dir() 返回的条目计数减少了 8 倍,clear_ce_flags_1() 中的循环将重新处理这些目录中的条目。

      通过将全局计数器插入unpack-tree.c 并使用trace2_data_intmax() 跟踪它们(在私人更改中,用于测试),我能够看到clear_ce_flags_1() 内部的循环处理了多少次以及处理了多少次clear_ce_flags_dir() 被调用。
      随着当前的变化,这些中的每一个都至少减少了 8 倍。
      重复多级目录时,会发生大于 8 的因数。

      具体来说,在 Linux 内核 repo 中,命令

      git sparse-checkout set LICENSES
      

      将工作目录限制为仅位于根目录和 LICENSES 目录中的文件。
      以下是测量的计数:

      clear_ce_flags_1 循环块:

      Before: 11,520
      After:   1,621
      

      clear_ce_flags_dir 来电:

      Before: 7,048
      After:    606
      

      虽然这些数字非常惊人,但在每种情况下花费在clear_ce_flags_1() 上的时间都不到一毫秒,因此无法以端到端时间来衡量改进。


      在 Git 2.26(2020 年第一季度)中,稀疏结账功能中的一些粗糙边缘,尤其是在锥形模式周围,已被清理干净。

      commit f998a3fcommit d2e65f4commit e53ffe2commit e55682ecommit bd64de4commit d585f0ecommit 4f52c2ccommit 9abc60f(2020 年 1 月 31 日)和commit 9e6d3e6、@987@、@987 commit 47dbf10commit 3c75406commit d622c34commit 522e641(2020 年 1 月 24 日)Derrick Stolee (derrickstolee)
      请参阅 Jeff King (peff)commit 7aa9ef2(2020 年 1 月 24 日)。
      (由 Junio C Hamano -- gitster -- 合并于 commit 433b8aa,2020 年 2 月 14 日)

      sparse-checkout: 修复锥形模式行为不匹配

      报告人:Finn Bryant
      签字人:Derrick Stolee

      稀疏签出功能中特殊的“锥形模式”的目的是始终匹配相同的稀疏签出文件匹配的相同模式,就像禁用锥形模式时一样。

      当在锥形模式下将文件路径赋予“git sparse-checkout set”时,锥形模式会不正确地将文件匹配为递归路径。
      在设置 skip-worktree 位时,文件不期望 MATCHED_RECURSIVE 响应,因此这些被排除在匹配的锥体之外。

      通过检查 MATCHED_RECURSIVEMATCHED 来修复此错误,并添加一个防止回归的测试。

      The documentation 现在包括:

      启用core.sparseCheckoutCone 时,输入列表被视为 目录列表,而不是稀疏结帐模式。
      该命令将模式写入稀疏签出文件,以包括这些目录(递归)中包含的所有文件以及祖先目录的兄弟文件。
      输入格式与git ls-tree --name-only 的输出相匹配。这包括将以双引号 (") 开头的路径名解释为 C 风格的带引号的字符串。


      在 Git 2.26(2020 年第一季度)中,“git sparse-checkout”学习了新的“add”子命令

      参见commit 6c11c6a(2020 年 2 月 20 日)和 commit ef07659commit 2631dc8commit 4bf0c06commit 6fb705a(2020 年 2 月 11 日)Derrick Stolee (derrickstolee)
      (由 @987654417 合并@in commit f4d7dfc,2020 年 3 月 5 日)

      sparse-checkout: 创建 'add' 子命令

      签字人:Derrick Stolee

      使用稀疏结帐功能时,用户可能希望逐步扩展其稀疏结帐模式集
      允许使用新的“添加”子命令添加模式。

      这与 'set' 子命令没有太大区别,因为我们仍然希望允许 '--stdin' 选项,并在锥体模式和其他模式下将输入解释为目录。

      在圆锥模式下,我们正在扩大圆锥。
      A/B 已经是锥体中的目录时,这实际上可能会减少添加目录A 时的模式集。测试不同的案例:兄弟姐妹、父母、祖先。

      当不处于锥形模式时,我们只能假设模式应该附加到稀疏检出文件中。

      还有:

      sparse-checkout:使用 Windows 路径

      签字人:Derrick Stolee

      在使用 Windows 时,用户可以将“git sparse-checkoutset A\B\C' to add the Unix-style path A/B/C”运行到他们的稀疏结帐模式。

      在我们将字符串“A/B/C”添加到递归哈希集之前,规范化输入路径会将反斜杠转换为斜杠。


      sparse-checkout 模式一直被禁止排除所有路径,留下一棵空的工作树。

      在 Git 2.27(2020 年第二季度)中,这一限制已被解除。

      参见Derrick Stolee (derrickstolee)commit ace224a(2020 年 5 月 4 日)。
      (由 Junio C Hamano -- gitster -- 合并于 commit e9acbd6,2020 年 5 月 8 日)

      sparse-checkout: 停止阻塞空工作目录

      报告人:Lars Schneider
      签字人:Derrick Stolee

      删除更新稀疏签出时的错误条件留下一个空的工作目录。

      9e1afb167 中添加了此行为(“稀疏结帐:禁止空工作树”,2009-08-20,Git v1.7.0-rc0 -- merge)。

      评论添加在a7bc906f2(“添加解释为什么我们不允许稀疏结帐到空工作树”,2011-09-22,Git v1.7.8-rc0 -- merge)响应84563a624 中的“可疑”评论(“[unpack-trees.c](https://github.com/git/git/blob/ace224ac5fb120e9cae894e31713ab60e91f141f/unpack-trees.c):化妆品修复”,2010- 12-22,Git v1.7.5-rc0 -- merge)。

      使用最近的“cone mode”和“git sparse-checkout init [--cone]”命令,设置合理的sparse-checkout模式集是很常见的

      /*
      !/*/
      

      仅匹配根目录下的文件。如果存储库没有这样的文件,那么他们的“git sparse-checkout init”命令将会失败。

      既然我们希望这是一种常见的模式,我们不应该让命令在空的工作目录上失败。
      如果结果令人困惑,则用户可以使用“git sparse-checkout disable”或“git sparse-checkout set”进行恢复。这在使用锥形模式时尤其简单。

      【讨论】:

      • 您将整个文档粘贴在那里,好像需要整个文档来回答问题......
      • 删除文档的副本/粘贴,并改为链接到它。这是不必要的信息分叉。我们的业务是组织信息,而不是分叉。
      【解决方案4】:

      我遇到了同样的问题。我用类似的东西修复了它:

      !presentations/heavy_presentation
      presentations/*
      

      我如何理解它的工作原理: 它按规则读取文件。如果包含某些内容,它将包含包含该单词的所有路径,并且在稀疏结帐结束之前它不会再更改其状态。如果您在包含之前添加排除规则,我认为它会先删除文件,然后将所有文件标记为包含。

      我不完全确定,这是我根据我的经验所设想的并且一直在为我工作。我希望它会对某人有所帮助。

      【讨论】:

        【解决方案5】:

        简答:

        git sparse-checkout set /* !/presentations/heavy_presentation/
        git sparse-checkout init [--cone]
        

        --cone 选项:仅与少数模式/小型 repo 无关,但通常用于加速。需要sparse-checkout / CONE PATTERN SET 文档中解释的模式的某种规范顺序)。稍后也可以通过以下方式介绍:

        git config core.sparseCheckoutCone true
        

        【讨论】:

          猜你喜欢
          • 2020-11-23
          • 1970-01-01
          • 2017-08-31
          • 2016-06-18
          • 1970-01-01
          • 2019-11-19
          • 2017-06-07
          • 2016-05-07
          • 2021-05-26
          相关资源
          最近更新 更多