5

有很多关于稀疏结帐的文章和 SO 问题。不幸的是,我没有找到具体的例子。我想得到以下示例工作:

创建子模块

cd ~
mkdir sub && cd $_
git init 
mkdir foo && touch $_/foo
mkdir bar && touch $_/bar
git add .
git commit -am "Initial commit"

创建项目

cd ~
mkdir project && cd $_
git init
git submodule add ../sub sub
git config -f .gitmodules submodule.sub.shallow true
git config -f .gitmodules submodule.sub.sparsecheckout true
echo foo/* > .git/modules/sub/info/sparse-checkout
git commit -am "Initial commit"
git submodule update
cd sub
git checkout .

这一点我期望sub文件夹只包含foo/foonot bar。不幸的是,它不起作用:

$ ls
bar/ foo/

我怎样才能让它工作?

4

2 回答 2

7

git submodule add本身检查子模块。

对我来说成功的是:

git init
# I did not find a way to add submodule in 1 step without checking out
git clone --depth=1 --no-checkout ../sub sub
git submodule add ../sub sub
git submodule absorbgitdirs
# note there is no "submodule.sub.sparsecheckout" key
git -C sub config core.sparseCheckout true
# note quoted wildcards to avoid their expansion by shell
echo 'foo/*' >>.git/modules/sub/info/sparse-checkout
git submodule update --force --checkout sub
于 2017-08-15T09:01:53.633 回答
4

要添加到max630答案

  • 从 Git 2.25(2020 年第一季度)开始,您将使用新命令git sparse-checkout

  • 在 Git 2.28(2020 年第三季度)中,sparse checkout记录了设置对子模块的影响。

这意味着如果您使主存储库本身稀疏检出,除了子模块(已经稀疏,如 max630 的回答),git sparse-checkout在主存储库上使用不会对子模块产生负面影响(即在有工作时错误地删除它进展)。

请参阅Elijah Newren ( ) 的提交 e7d7c73(2020 年 6 月 10 日(由Junio C Hamano 合并——提交 81be89e中,2020 年 6 月 22 日)newren
gitster

git-sparse-checkout: 阐明与子模块的交互

签字人:Elijah Newren
审核人:Derrick Stolee

暂时忽略 sparse-checkout 功能,如果有一个子模块并在其中创建本地分支,其中包含未推送的更改,并且可能会向其中添加一些未跟踪的文件,那么我们希望避免意外删除这样的子模块。

因此,例如使用git.git,如果您运行

git checkout v2.13.0

然后 sha1collisiondetection/ 子模块不会被删除,即使它在 v2.14.0 之前作为子模块不存在。

同样,如果您之前只签出 v2.13.0 并运行

git checkout v2.14.0

尽管是 v2.14.0 的一部分,但 sha1collisiondetection/ 子模块不会自动初始化。

在这两种情况下,git 都需要单独初始化或取消初始化子模块。

此外,我们还在其他命令中对子模块进行了特殊处理,例如 clean,它需要两个--force标志来删除未跟踪的子模块,有些命令有一个--recurse-submodules标志。

sparse-checkout 与 checkout 非常相似,其名称相似——它在工作副本中添加和删除文件。

然而,出于同样的避免数据丢失的原因,我们不想使用 checkout 从工作副本中删除子模块,我们也不想使用 sparse-checkout 来完成。

所以子模块需要单独初始化或者去初始化;更改 sparse-checkout 规则不应自动触发子模块的删除或激活。

我相信git sparse-checkout关于子模块的先前措辞只是关于这个特定问题。

不幸的是,前面的措辞可以被解释为暗示子模块应该被认为是活跃的,而不管稀疏模式如何。

更新措辞以避免做出这样的暗示。

考虑两个措辞差异变得重要的示例情况可能会有所帮助:

在未来,我们希望用户能够运行类似的命令

git clone --sparse=moduleA --recurse-submodules $REPO_URL

并自动设置稀疏路径,并自动初始化稀疏路径中的子模块。

我们不希望使用该命令自动初始化任何路径中的所有子模块。

同样,我们希望能够做类似的事情

git -c sparse.restrictCmds grep --recurse-submodules $REV $PATTERN

并在记录的稀疏模式中$REV搜索。$PATTERN

我们希望它递归到那些稀疏模式中的子模块,但不希望递归到与稀疏模式不匹配的目录以搜索可能的子模块。

所以文档现在包括:

如果您的存储库包含一个或多个子模块,则会根据与git submodule命令的交互来填充子模块。
具体来说,git submodule init -- <path>将确保子模块 at<path>存在,而git submodule deinit [-f] -- <path>将删除子模块 at 的文件<path>(包括任何未跟踪的文件、未提交的更改和未推送的历史记录)。
类似于 sparse-checkout 从工作树中删除文件但仍然在索引中保留条目的方式,取消初始化的子模块从工作目录中删除但仍然在索引中具有条目。

由于子模块可能有未推送的更改或未跟踪的文件,因此删除它们可能会导致数据丢失。
因此,更改稀疏包含/排除规则不会导致已签出的子模块从工作副本中删除。
换句话说,checkout即使在删除或添加子模块的分支之间切换时也不会导致子模块被自动删除或初始化,使用sparse-checkout减少或扩大“有趣”文件的范围也不会导致子模块被自动取消初始化或初始化.

此外,上述事实意味着工作副本中可能不存在“跟踪”文件的原因有多种:来自稀疏签出的稀疏模式应用程序和子模块初始化状态。
因此,git grep对工作副本中的跟踪文件进行类似处理的命令可能会返回受这些限制中的一个或两个限制的结果。


在 Git 2.31(2021 年第一季度)中,“ git grepman已被调整为仅限于稀疏结帐路径。

由于您可能需要git grep稀疏签出子模块,因此这很重要。

请参阅Matheus Tavares ( ) 的提交 42d906b(2021 年 2 月 9 日(由Junio C Hamano 合并——提交 628c13c中,2021 年 2 月 25 日)matheustavares
gitster

grep:尊重工作树搜索的稀疏结帐

建议人:Elijah Newren
签字人:Matheus Tavares
审核人:Elijah Newren

在稀疏签出的存储库上,当条目与搜索路径规范匹配并设置了位时, man(不带)最终会搜索缓存。git grep--cachedSKIP_WORKTREE

这很令人困惑,因为稀疏路径不应该在工作树搜索中(因为它们没有被检出),而且因为输出混合了工作树和缓存结果而不区分它们。
(请注意,在包含路径grep的工作树搜索中也会使用缓存。 但在这种情况下,重点是假设索引条目和文件的内容是相同的。 这不适用于稀疏路径的情况,文件甚至不存在的地方。)--assume-unchanged

通过教 grep 遵守工作树搜索的稀疏签出规则来解决这个问题。
如果用户想要 grep 当前稀疏检出定义之外的路径,他们可以更新稀疏规则以实现文件,或者用于--cached搜索索引中注册的所有 blob。

于 2020-06-28T01:01:26.620 回答