Git稀疏结账,排除

krl*_*mlr 12 git sparse-checkout

根据这个帖子,Git的sparse-checkout功能中的排除应该被实现.是吗?

假设我有以下结构:

papers/
papers/...
presentations/
presentations/heavy_presentation
presentations/...
Run Code Online (Sandbox Code Playgroud)

现在我想presentations/heavy_presentation从收银台中排除,而将其余部分留在收银台.我没有设法让这个运行.什么是正确的语法?

Von*_*onC 9

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

Git 2.37(2022 年第 3 季度)将圆锥模式设为默认模式。请参阅此答案的最后一部分。


首先,这是一个扩展示例,从使用选项的快速克隆--filter开始:

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
Run Code Online (Sandbox Code Playgroud)

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

/*
!/*/
Run Code Online (Sandbox Code Playgroud)

含义:只有顶层文件,没有子文件夹。
如果你不需要顶部文件,你需要避免锥体模式:

/*
!/*/
Run Code Online (Sandbox Code Playgroud)

我只是想弄清楚要传递给什么git sparse-checkout set来排除某些东西。

那更棘手。

解决方法可能包括明确包含其他所有内容。

这应该会导致该presentations目录包含在稀疏结帐中,但不包含heavy_presentation子目录

那将是:

# 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
Run Code Online (Sandbox Code Playgroud)

详细信息:

(更多信息请参见Derrick Stolee的“ Bring your monorepo down to size withsparse-checkout ” )

因此,不仅排除子文件夹确实有效,而且使用稀疏签出的“圆锥”模式(使用 Git 2.25)会更快。

请参阅Junio C Hamanogitster合并的提交-- --在2019 年 12 月 25 日的提交 bd72a08中:

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

签署人:Derrick Stolee

随着索引中模式数量和条目数量的增长,稀疏检验功能可以具有二次方性能。
如果有 1,000 个模式和 1,000,000 个条目,则该时间可能非常重要。

创建一个新的布尔配置选项core.sparseCheckoutCone,以指示我们期望稀疏签出文件包含一组更有限的模式。
这是一个单独的配置设置,以core.sparseCheckout避免通过引入三态选项来破坏旧客户端。

手册config包括:

`core.sparseCheckoutCone`:
Run Code Online (Sandbox Code Playgroud)

启用稀疏结账功能的“圆锥模式”。
当稀疏检出文件包含一组有限的模式时,此模式可提供显着的性能优势。

手册git sparse-checkout详细信息:

锥形图案套装

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

圆锥图案集中可接受的图案有:

  1. 递归:包含目录内的所有路径。
  2. 父级:包含目录中紧邻的所有文件。

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

默认情况下,运行时git sparse-checkout init,根目录将添加为父模式。此时,稀疏签出文件包含以下模式:

/*
!/*/
Run Code Online (Sandbox Code Playgroud)

这表示“包含 root 中的所有内容,但不包含 root 以下两级的内容”。
如果我们随后将文件夹添加A/B/C为递归模式,则文件夹AA/B将添加为父模式。
现在生成的稀疏签出文件是

/*
!/*/
/A/
!/A/*/
/A/B/
!/A/B/*/
/A/B/C/
Run Code Online (Sandbox Code Playgroud)

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

如果core.sparseCheckoutCone=true,那么 Git 将解析稀疏签出文件,期望这些类型的模式。
如果模式不匹配,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 年第 1 季度)中
(由Junio C Hamano 合并 -- gitster--于2020 年 2 月 5 日提交 ea46d90中)

doc: sparse-checkout: 提及--cone选项

签署人:Matheus Tavares
确认人:Derrick Stolee

af09ce2 (" sparse-checkout: init 并以锥体模式设置", 2019-11-21, Git v2.25.0-rc0 -- merge )中,' --cone' 选项被添加到 ' git sparse-checkoutinit' 中。

将其记录在git sparse-checkout

包括了:

--cone提供时,core.sparseCheckoutCone设置也会被设置,从而允许使用一组有限的模式获得更好的性能。

(上面提到的“模式集”,在CONE PATTERN SET这个答案的“”部分)


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

sparse-checkout:对圆锥模式使用哈希图

帮助者:Eric Wong
帮助者:Johannes Schindelin
签字人:Derrick Stolee

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

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

/$folder/
!/$folder/*/
Run Code Online (Sandbox Code Playgroud)

这导致稀疏签出文件包含 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)
Run Code Online (Sandbox Code Playgroud)

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

虽然这个例子是人为的,但它演示了这些模式如何减慢稀疏结账功能。

和:

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()。这是通过更改哈希算法和哈希图比较方法以选择性地使用不区分大小写的方法来完成的。

启用此功能后,哈希算法的性能成本会很小。
为了弄清楚最坏的情况,在具有深层目录结构的存储库上运行以下命令:

git ls-tree -d -r --name-only HEAD |
git sparse-checkout set --stdin
Run Code Online (Sandbox Code Playgroud)

“set”命令被定时为core.ignoreCase禁用或启用。
对于具有悠久历史的回购来说,数字是

core.ignoreCase=false: 62s
core.ignoreCase=true:  74s (+19.3%)
Run Code Online (Sandbox Code Playgroud)

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

core.ignoreCase=false: 3.1s
core.ignoreCase=true:  3.6s (+16%)
Run Code Online (Sandbox Code Playgroud)

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

因此,我们可以证明这一变化的成本,但它不太可能对任何合理的稀疏结账锥体产生影响。


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

请参阅Derrick Stolee ( )的提交 4fd683b提交 de11951(2019 年 12 月 30 日)。(由Junio C Hamano 合并 -- --提交 c20d4fd中,2020 年 1 月 6 日)derrickstolee
gitster

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

签署人:Derrick Stolee

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

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

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

git sparse-checkout list | git sparse-checkout set --stdin
Run Code Online (Sandbox Code Playgroud)

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


最近在这个版本中添加的代码,用于在稀疏锥体模式下移动到索引中同一目录中的条目之外的条目,没有错误地计算要跳过的条目数,这一问题已在 Git 2.25.1 中得到纠正(2020 年 2 月)。

请参阅Junio C Hamano ( )的提交 7210ca4(2020 年 1 月 27 日)。 请参阅Derrick Stolee 通过 GitGitGadget (``)提交的提交 4c6c797(2020 年 1 月 10 日)。(由Junio C Hamano 合并 -- --提交 043426c中,2020 年 1 月 30 日)gitster

gitster

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

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

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

eb42feca(“ unpack-trees:在圆锥模式下进行更少的哈希”,2019-11-21,Git v2.25.0-rc0 -合并在批#0中列出)引入了此性能功能。旧机制依赖于调用返回的计数,但新机制通过从“”中clear_ce_flags_1()减去“”来计算行数,以找到范围的大小。 然而,该方程是错误的,因为它除以。这不是指针算术的工作原理!cache_endcache
sizeof(struct cache_entry *)

为 2.25.0 版本做准备的 Windows 版 Git Coverity 版本发现了此问题,并发出警告:

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.
Run Code Online (Sandbox Code Playgroud)

这个警告是正确的。


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

请参阅提交 f998a3f提交 d2e65f4提交 e53ffe2、提交e55682e提交 bd64de4提交 d585f0e提交 4f52c2c提交 9abc60f(2020 年 1 月 31 日)和提交 9e6d3e6提交 41de0c6提交 47dbf10提交3c75406提交 d622c34提交 522e641(24 2020 年 1 月),作者:Derrick Stolee ( derrickstolee)
请参阅Jeff King ( )的提交 7aa9ef2(2020 年 1 月 24 日)。(由Junio C Hamano 合并 -- --提交 433b8aa中,2020 年 2 月 14 日)peff
gitster

sparse-checkout:修复锥体模式行为不匹配的问题

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

稀疏检出功能中特殊“圆锥模式”的目的是始终匹配与禁用圆锥模式时相同的稀疏检出文件所匹配的相同模式。

当在锥体模式下将文件路径指定给“ git sparse-checkoutset”时,锥体模式会错误地将文件匹配为递归路径。
当设置跳过工作树位时,文件并不期望响应MATCHED_RECURSIVE,因此这些文件被排除在匹配的锥体之外。

通过检查MATCHED_RECURSIVE此外MATCHED并添加防止回归的测试来修复此错误。

该文档现在包括:

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


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

请参阅提交 6c11c6a(2020 年 2 月 20 日),以及提交 ef07659提交 2631dc8提交 4bf0c06提交 6fb705a(2020 年 2 月 11 日),作者:Derrick Stolee ( derrickstolee)
(由

  • 您将整个文档粘贴在那里,就好像需要整件事来回答问题一样...... (5认同)
  • 删除文档的副本/粘贴,然后链接到它。这是不必要的信息分歧。我们的业务是组织信息,而不是分叉信息。 (3认同)

  • exp*_*ert 7

    遗憾的是,上述方法都不适合我,因此我花了很长时间尝试不同的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/*
    /*
    
    Run Code Online (Sandbox Code Playgroud)

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


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

    我有git 1.9


    man*_*lds 6

    我希望下面的东西可以工作:

    /*
    !presentations/heavy_presentation
    
    Run Code Online (Sandbox Code Playgroud)

    但事实并非如此.我确实尝试了很多其他组合.我认为排除没有正确实施,并且它周围有bug(仍然)

    就像是:

    presentations/*
    !presentations/heavy_presentation
    
    Run Code Online (Sandbox Code Playgroud)

    确实有效,你将获得没有heavy_presentation文件夹的presentation文件夹.

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

    • 你的第一个解决方案在 Windows 上的 git 2.21.0 中对我有用 (2认同)

    Den*_*s P 6

    使用 Git 2.37(2022 年 6 月发布),一切变得更加容易。要排除一个文件夹和一些与掩码匹配的文件(只是为了提供比问题所要求的更一般/有用的示例),我这样做了:

    git sparse-checkout set --no-cone "/*" "!/folder/" "!/path/to/dist/*.map"
    
    Run Code Online (Sandbox Code Playgroud)

    这非常直观(好吧,在花了几个小时找到这个公式之后)。文件夹中的folder所有文件也完全消失。其他什么都没碰。*.mappath/to/dist

    一些重要的部分:

    1. 如果本地存储库有任何未暂存/忽略的文件,我强烈建议您在开始之前对其进行备份。我的第一次尝试(没有“/*”等)很可怕 - 好像我的大部分数据都消失了。下面的 #5 似乎有助于恢复一切,但你永远无法确定一个大的回购协议......

    2. "/*"是神奇的一块。它要求 GIT 包含稍后未排除的所有内容。没有它它就无法工作(删除大量存储库内容)。它必须排在列表的第一位!

    3. 您可能需要set +H该命令才能通过(bash 将其视为!特殊命令)。然后set -H恢复默认的 bash 行为。

    4. 我建议通过输入以下内容来检查 GIT 对您使用的路径的解释:

      cat .git/info/sparse-checkout

      在为我的案例找到“公式”之前,我多次对结果感到惊讶(例如参见#6)。

    5. ls运行命令后,对一些存储库路径执行此操作。如果出现问题,则应git sparse-checkout disable恢复所有丢失的文件。至少这对我来说效果很好。

    6. 最好对所有路径使用引号。在“/*”中尤其重要!这是我在 .git/info/sparse-checkout 中使用不带引号时得到的内容(每个都来自新行,由于某种原因 stackoverflow 的格式不太好):

      /bin /dev /etc /home /lib /lib64 /opt /proc /root /run /sbin /tmp /usr /var !folder/ !path/to/dist/*.map

      你可以想象这些模式并不是我想说的......

    7. 注意到处都是斜线("!/folder/")。如果省略 ( "!folder/"),则具有此类名称的文件夹将被删除层次结构中的所有位置,而不仅仅是顶层。

    8. --no-cone现在很重要。这是过去的默认模式,当在互联网上查看旧的建议时,这可能会带来很多混乱!如果你想更好地理解事情,GIT 文档对此进行了详细说明。

    希望这对某人有帮助。


    更新:向排除的路径添加了前导斜杠,如上面#7 中所述。