如何用Git进行子模块稀疏检测?

时间:2017-08-15 07:19:12

标签: git git-submodules git-sparse-checkout

关于稀疏结账有很多文章和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/foo而不是bar。不幸的是,它不起作用:

$ ls
bar/ foo/

我怎样才能让它发挥作用?

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

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

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

请参见commit e7d7c73Elijah Newren (newren)(2020年6月10日)。
(由Junio C Hamano -- gitster --commit 81be89e中合并,2020年6月22日)

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

签名人:伊利亚·纽伦
作者:Derrick Stolee

暂时忽略稀疏签出功能,如果一个人拥有一个子模块,并在其中创建了具有未经推送的更改的本地分支,并且可能向其中添加了一些未跟踪的文件,那么我们将避免意外删除这样的子模块。

例如,如果使用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标志。

稀疏检出与检出非常相似,以相似的名称证明:它可以从工作副本中添加和删除文件。

但是,出于相同的避免数据丢失的原因,我们不想通过签出从工作副本中删除子模块,我们也不想通过稀疏签出来进行操作。

因此子模块需要单独初始化或取消初始化;更改稀疏签出规则不应自动触发子模块的移除或激活。

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

不幸的是,前面的措辞可以解释为暗示子模块应该被认为是活动的,而与稀疏模式无关。

更新措词,以免造成这种暗示。

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

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

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

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

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

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

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

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

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

所以the documentation现在包括:

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

由于子模块可能具有未按下的更改或未跟踪的文件,因此删除子模块可能会导致数据丢失。
因此,更改稀疏包含/排除规则不会导致已经签出 子模块要从工作副本中删除。
换句话说,就像checkout一样,即使在删除或添加的分支之间切换,也不会导致子模块被自动删除或初始化。 子模块,使用sparse-checkout缩小或扩展“有趣”文件的范围也不会导致子模块被自动取消初始化或初始化。

此外,以上事实意味着“跟踪”文件可能不存在于工作副本中有多种原因:稀疏检出的稀疏模式应用程序和子模块初始化状态。
因此,在工作副本中跟踪文件上运行的诸如git grep之类的命令可能会返回受这些限制之一或全部限制的结果。