带排除的Git稀疏校验

6za6bjd0  于 2023-01-28  发布在  Git
关注(0)|答案(6)|浏览(208)

根据this thread,Git的sparse-checkout feature中的exclusion应该被实现,是吗?
假设我有下面的结构:

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

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

nsc4cvqm

nsc4cvqm1#

在Git 2.25(Q1 2020)中,稀疏 checkout 工作树的管理获得了一个专用的" sparse-checkout " command
Git 2.37(Q3 2022)将圆锥模式设为默认模式,请参阅最后一节。
首先,这里是一个扩展示例,从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将包含以下模式:

/*
!/*/

含义:仅顶层文件,无子文件夹。
如果您不想使用顶锉,则需要 * 避免 * 锥形模式:

# 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

详情如下:
(See更多信息请访问**Derrick Stolee**中的"Bring your monorepo down to size with sparse-checkout")
因此,排除子文件夹不仅有效,而且在稀疏 checkout 的"cone"模式下(Git 2.25),它的工作速度会更快。
参见Ed Maste ( emaste )commit 761e3d2(2019年12月20日)。
参见commit 190a65f(2019年12月13日),以及第commit cff4e91条、第commit 416adc8条、第commit f75a69f条、第commit fb10ca5条、第commit 99dfa6f条、第commit e091228条、第commit e9de487条、第commit 4dcd4de条、第commit eb42fec条、第commit af09ce2条、第commit 96cc8ab条、第commit 879321e条、第commit 72918c1条、第commit 7bffca9条、第commit f6039a9条,第22天、第23天、第24天(2019年11月21日)和第25天。
参见Jeff Hostetler ( Jeff-Hostetler )commit e6152e3(2019年11月21日)。
(由Junio C Hamano -- gitster --合并至commit bd72a08,2019年12月25日)

sparse-checkout:添加"锥形"模式

签署人:德里克·斯托利
随着索引中的模式数和条目数的增长,稀疏检出特性可以具有二次性能。
如果有1,000个模式和1,000,000个条目,这个时间可能非常重要。
创建一个新的Boolean配置选项core. sparseCheckoutCone,以指示我们希望稀疏 checkout 文件包含更有限的模式集。
这是一个独立于core.sparseCheckout的配置设置,以避免通过引入三态选项来破坏旧客户端。
config手册页包括:

`core.sparseCheckoutCone`:

启用稀疏检出功能的"锥形模式"。
当稀疏 checkout 文件包含有限的模式集时,此模式将提供显著的性能优势。
git sparse-checkout手册页详细信息:

锥形图案集

完整的模式集允许任意模式匹配和复杂的包含/排除规则。
更新索引时,这些可能会导致O(N*M)模式匹配,其中N是模式数,M是索引中的路径数。为了解决此性能问题,在启用core.spareCheckoutCone时允许使用更严格的模式集。
圆锥模式集中可接受的模式为:
1.* 递归:* 包含目录中的所有路径。
1.* 父级:* 包含直接位于目录中的所有文件。
除了以上两种模式之外,我们还期望根目录下的所有文件都被包括在内,如果添加了递归模式,那么所有的前导目录都被添加为父模式。
默认情况下,当运行git sparse-checkout init时,根目录被添加为父模式。此时,sparse-checkout文件包含以下模式:

/*
!/*/

这意味着"包含根目录中的所有内容,但不包含根目录下两级的内容"。
如果我们随后将文件夹A/B/C添加为递归模式,则文件夹AA/B将被添加为父模式。
生成的稀疏 checkout 文件现在为

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

在这里,顺序很重要,因此负面模式会被文件中较低位置的正面模式覆盖。
如果core.sparseCheckoutCone=true,Git将解析稀疏 checkout 文件,期望这些类型的模式。
如果模式不匹配,Git会发出警告。
如果模式与预期的格式匹配,Git将使用更快的基于哈希的算法来计算sparse-checkout中的包含。
因此:

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

协助人:Eric Wong
协助人:约翰内斯·辛德林
签署人:德里克·斯托利
要使圆锥体图案集易于使用,请更新"git sparse-checkout (init|set)"的行为。
将"--cone"标志添加到"git sparse-checkout init"以设置配置选项"core.sparseCheckoutCone=true"。
当在cone模式下运行'git sparse-checkout set'时,用户只需要提供一个递归文件夹匹配列表,Git会自动为前导目录添加必要的父级匹配。
请注意,--cone选项仅在Git 2.26(2020年第一季度)中有记录
(由Junio C Hamano -- gitster --合并至commit ea46d90,2020年2月5日)

docsparse-checkout:提及--cone选项

签署人:马修·塔瓦雷斯
确认人:Derrick Stolee
af09ce2("sparse-checkout:初始化并设置为圆锥模式",2019年11月21日,Git v2.25.0-rc0--merge),在" git sparse-checkout初始化"中添加了" --cone "选项。
git sparse-checkout中记录:
其中包括:
当提供--cone时,还设置了core.sparseCheckoutCone设置,从而允许使用有限的模式集获得更好的性能。
(上文"CONE PATTERN SET"部分中的"模式集")
这种新的"锥形"模式会快多少?

sparse-checkout:使用散列表用于圆锥模式

协助人:Eric Wong
协助人:约翰内斯·辛德林
签署人:德里克·斯托利

稀疏校验中的"cone mode"选项所允许的父模式和递归模式有足够的限制性,我们可以避免使用正则表达式解析。一切都基于前缀匹配,所以我们可以使用散列集来存储稀疏校验文件中的前缀。当检查路径时,我们可以从路径中剥离路径条目,并检查散列集是否完全匹配。
作为测试,我为Linux存储库创建了一个锥模式稀疏 checkout 文件,它实际上包含了每个文件,它是通过获取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()调用所花费的时间。
虽然这个示例是人为设计的,但它演示了这些模式如何降低稀疏 checkout 特性的速度。
以及:

sparse-checkout:在圆锥体模式下,尊重核心。忽略大小写

签署人:德里克·斯托利
当用户在cone模式下使用稀疏检出特性时,他们使用"git sparse-checkout set <dir1> <dir2> ..."或"--stdin"添加模式,以便在stdin上逐行提供目录。
这种行为看起来很像用户键入"git add <dir1> <dir2> ..."的方式
如果启用了core.ignoreCase,则"git add"将使用不区分大小写的匹配来匹配输入。
sparse-checkout特征执行相同的操作。
unpack_trees()期间更新skip-worktree位时执行不区分大小写的检查。这是通过更改散列算法和散列表比较方法以选择使用不区分大小写的方法来完成的。
启用此选项后,哈希算法的性能开销很小。
为了梳理出可能出现的最坏情况,我们在具有深层目录结构的repo上运行了以下代码:

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

"set"命令是在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(Q1 2020)中,"git sparse-checkout list"子命令学会了在"cone"模式下以更简洁的形式输出。
参见commit 4fd683bcommit de11951(2019年12月30日)和Derrick Stolee ( derrickstolee )
(由Junio C Hamano -- gitster --合并至commit c20d4fd,2020年1月6日)

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

签署人:德里克·斯托利
启用core.sparseCheckoutCone时,"git sparse-checkout set"命令将目录列表作为输入,然后创建稀疏 checkout 模式的有序列表,以便递归地包括这些目录,并且还包括父目录的所有同级条目。
列出模式不如目录本身对用户友好。
在锥形模式中,只要模式与预期的锥形模式模式类型匹配,就可以更改'git sparse-checkout list'的输出,使其仅显示创建模式的目录。
通过此更改,以下管道命令将不会更改工作目录:

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

唯一不起作用的情况是core.sparseCheckoutConetrue,但稀疏检出文件包含的模式与cone模式的预期模式类型不匹配。
本版本中最近添加的代码在稀疏圆锥模式下移动到索引中同一目录以外的条目时,没有正确计算要跳过的条目数,这一问题已在Git 2.25.1(February 2020)中得到纠正。
参见commit 7210ca4(2020年1月27日)。
参见commit 4c6c797(2020年1月10日),作者为Derrick Stolee via GitGitGadget (``)
(由Junio C Hamano -- gitster --合并至commit 043426c,2020年1月30日)

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

报告人:约翰内斯·申德林
签署人:德里克·斯托利
clear_ce_flags_dir()方法处理一个公共目录中的缓存项。返回的int是该目录处理的缓存项的数目。
当在cone模式下使用稀疏检出特性时,我们可以跳过对目录中完全包含或完全排除的条目的模式匹配。
eb42feca("unpack-trees:hash less 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版本而构建的Git for Windows 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.

此警告是正确的。
在Git 2.26(Q1 2020)中,稀疏校验特性中的一些粗糙边缘,特别是在cone模式周围,已经得到了清理。
请参见commit f998a3fcommit d2e65f4commit e53ffe2commit e55682ecommit bd64de4commit d585f0ecommit 4f52c2ccommit 9abc60f(2020年1月31日),以及第一天、第一天、第一天、第一天、第一天、第一天、第一天。
参见commit 7aa9ef2(2020年1月24日)。
(由Junio C Hamano -- gitster --合并到commit 433b8aa,2020年2月14日)

sparse-checkout:固定锥模式行为失配

报告人:芬恩·布莱恩特
签署人:德里克·斯托利
稀疏校验特性中特殊的"cone模式"的目的是始终匹配与禁用cone模式时相同的稀疏校验文件所匹配的相同模式。
在圆锥模式下将文件路径指定给"git sparse-checkout set"时,圆锥模式会将文件错误地匹配为递归路径。
当设置skip-worktree位时,文件不期望MATCHED_RECURSIVE响应,因此这些文件被排除在匹配锥之外。
通过检查MATCHED_RECURSIVE以及MATCHED来修复此错误,并添加防止回归的测试。
文档现在包括:
启用core.sparseCheckoutCone后,输入列表被视为目录列表,而不是稀疏检出模式。
该命令将模式写入稀疏 checkout 文件,以包括这些目录中包含的所有文件(递归地)以及祖先目录的同级文件。
输入格式与git ls-tree --name-only的输出匹配,包括将以双引号(")开头的路径名解释为C样式的带引号字符串。
在Git 2.26(2020年第一季度)中,"git sparse-checkout"学习了一个新的"add"子命令
参见commit 6c11c6a(2020年2月20日)和Derrick Stolee ( derrickstolee )commit ef07659commit 2631dc8commit 4bf0c06commit 6fb705a(2020年2月11日)。
(由Junio C Hamano -- gitster --合并至commit f4d7dfc,2020年3月5日)

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

签署人:德里克·斯托利
在使用稀疏 checkout 特性时,用户可能希望逐渐增加他们的稀疏 checkout 模式集
允许使用新的"add"子命令添加模式。
这与"set"子命令没有太大区别,因为我们仍然希望允许"--stdin"选项,并在处于cone模式时将输入解释为目录,否则解释为模式。
在圆锥体模式下,我们将增大圆锥体。
A/B已经是cone中的一个目录时,添加目录A实际上可以减少模式集。兄弟姐妹父母祖先。
当不在cone模式下时,我们只能假设模式应该附加到稀疏检出文件中。
以及:

sparse-checkout:使用Windows路径

签署人:德里克·斯托利
在使用Windows时,用户可以对其稀疏 checkout 模式运行'git sparse-checkoutset A\B\C' to add the Unix-style path A/B/C'。
在我们将字符串'A/B/C'添加到递归哈希集之前,规范化输入路径会将反斜杠转换为斜杠。
长期以来,稀疏检出模式一直被禁止排除所有路径,留下一个空的工作树。
在Git 2.27(Q2 2020)中,这个限制被取消了。
参见Derrick Stolee ( derrickstolee )commit ace224a(2020年5月4日)。
(由Junio C Hamano -- gitster --合并至commit e9acbd6,2020年5月8日)

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

报告人:拉尔斯·施奈德
签署人:德里克·斯托利
删除更新稀疏 checkout 时留下空工作目录的错误条件。
9e1afb167("稀疏检出:禁止空工作树",2009年8月20日,Git v1.7.0-rc0--merge)。
该评论是在a7bc906f2中添加的("添加解释为什么我们不允许稀疏 checkout 到空工作树",2011年9月22日,Git v1.7.8-rc0--merge),以回应84563a624中的一条"可疑"评论("[ unpack-trees.c ](https://git/git/blob/ace224ac5fb120e9cae894e31713ab60e91f141f/unpack-trees.c):外观修复",2010年12月22日,Git v1.7.5-rc0--merge)。
使用最近的"cone mode"和"git sparse-checkout init [--cone]"命令,通常可以设置一个合理的稀疏校验模式集

/*
!/*/

它只匹配根目录下的文件。如果存储库没有这样的文件,那么他们的"git sparse-checkout init"命令将失败。
既然我们认为这是一种常见模式,那么就不应该让命令在空的工作目录上失败。
如果是一个混乱的结果,那么用户可以用"git sparse-checkout disable"或"git sparse-checkout set"来恢复,这在使用锥形模式时尤其简单。
在Git 2.37(Q3 2022)中,弃用稀疏校验特性的非锥形模式。
请参见第一电子112页、第一电子113页、第一电子114页、第一电子115页、第一电子116页、第一电子117页、第一电子118页、第一电子119页、第一电子120页(2022年4月22日)。
(由Junio C Hamano -- gitster --合并至commit 377d347,2022年6月3日)

sparse-checkout:使--cone成为缺省值

签署人:伊莱贾·纽伦

使圆锥体模式成为默认模式,并相应地更新文档。
git config现在在其手册页中包括:
通过将此变量设置为"false",可以请求"非圆锥模式"以允许指定更灵活的图案。
git sparse-checkout现在在其手册页中包括:
除非core.sparseCheckoutCone被显式设置为false,否则Git将解析稀疏 checkout 文件,并期待这些类型的模式。如果模式不匹配,Git将发出警告。如果模式确实匹配预期的格式,Git将使用更快的基于哈希的算法来计算稀疏 checkout 中的包含。
以及:

git-sparse-checkout.txt:锥形模式默认值的措辞更新

签署人:伊莱贾·纽伦
既然cone模式是默认模式,我们就想把注意力集中在set/add的参数上,将其设置为目录而不是模式,并且提供一个更早的提示可能是有意义的,即来自前导目录的文件也会被包括在内。
git sparse-checkout现在在其手册页中包括:
默认情况下,输入列表被视为目录列表,与git ls-tree -d --name-only的输出匹配。
这包括将以双引号(")开头的路径名解释为C样式的加引号字符串。
请注意,指定目录下的所有文件(任何深度)都将包含在稀疏检出中,以及给定目录或其任何祖先的同级文件(有关详细信息,请参阅下面的"锥形图案集")。
在过去,这不是默认设置,需要指定--cone或启用core.sparseCheckoutCone

hgc7kmma

hgc7kmma2#

我也遇到过同样的问题。我用类似的方法解决了它:

!presentations/heavy_presentation
presentations/*

我如何理解它的工作原理:它会一条一条地读取文件,如果包含了某个内容,它会包含所有包含该单词的路径,并且在稀疏 checkout 结束之前不会改变它的状态,如果在包含之前添加排除规则,我认为它会先删除文件,然后将所有文件标记为包含。
我不是很确定,这是我根据自己的经验所做的假设,也是我一直在做的事情。我希望它能帮助到一些人。

axr492tv

axr492tv3#

简短回答:

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

--cone选项:不适用于少数模式/小型存储库,但一般情况下可以提高速度。要求模式具有特定的规范顺序,如sparse-checkout/CONE PATTERN SET文档所述。

git config core.sparseCheckoutCone true
ha5z0ras

ha5z0ras4#

Git 2.37(2022年6月发布)要简单得多。为了排除一个文件夹和几个匹配掩码的文件(只是为了提供比问题更通用/更有用的例子),我这样做了:

git sparse-checkout set --no-cone "/*" "!/folder/" "!/path/to/dist/*.map"

这是非常直观的(好吧,在花了几个小时找到这个公式之后)。folder完全消失了,path/to/dist文件夹中的所有*.map文件也消失了。其他什么都没有动。
一些重要的信息:
1.我强烈建议备份您的本地存储库之前开始如果它有任何unstaged/忽略的文件。我的第一次尝试(没有"/*"等)是可怕的-好像我的大部分数据消失了。#5下面似乎有助于恢复一切,但你永远不知道肯定与一个大的存储库...

  1. "/*"是一个神奇的部分。它要求GIT包含以后不排除的所有内容。没有它就不能工作(删除大量repo内容)。它必须在列表中排在第一位!
    1.您可能需要set +H才能使命令通过(bash将!视为一个特殊命令),然后需要set -H来恢复默认的bash行为。
    1.我建议通过键入以下命令来检查GIT对您使用的路径的解释:
    cat .git/info/sparse-checkout
    在为我的案例找到"公式"之前,我对结果感到惊讶了好几次(例如,见#6)。
    1.在运行命令后,对一些repo路径执行ls。如果出现问题,那么git sparse-checkout disable应该恢复所有丢失的文件。至少在我的情况下,这工作得很好。
    1.最好对所有路径都使用引号在"/*"中尤其重要!下面是我在使用. git/info/sparse-checkout时没有使用引号时得到的结果(每一个都来自新行,由于某种原因stackoverflow的格式不太好):
    /bin/dev/etc/home/lib/lib64/opt/proc/root/运行/sbin/临时文件夹/usr/var!文件夹/!路径/到/dist/. map
    你可以想象这些模式不是我想说的...
    1.
    * 注意所有地方都要使用前导斜杠**("!/folder/")。如果省略("!folder/"),则具有此名称的文件夹将在层次结构中的所有地方删除,而不仅仅是顶层。
  2. --no-cone现在很重要。这是过去的默认模式,当你在互联网上查看旧的建议时,这可能会引入很多混乱! GIT docs详细说明了这一点,如果你想更好地理解的话。
    希望这能帮到什么人。
    • 更新**:在排除的路径中添加了前导斜杠,如上文#7所述。
flvlnr44

flvlnr445#

遗憾的是,以上这些都不适合我,所以我花了很长时间尝试不同的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

0tdrvxhp

0tdrvxhp6#

我本以为下面的方法会奏效:

/*
!presentations/heavy_presentation

但是它没有。我尝试了很多其他的组合。我认为exclude没有被正确实现,并且它周围有bug(仍然)
比如:

presentations/*
!presentations/heavy_presentation

确实工作,虽然你会得到演示文件夹没有heavy_presentation文件夹。
因此,解决方法是显式地包含所有其他内容。

相关问题