如何仅在git子模块中提取最新提交

时间:2016-11-27 21:47:19

标签: git

有没有办法我只能在git子模块中提取最新的提交?我试图将boost作为git子模块放在一些项目中,但由于包含所有内容的boost repo非常重量级,我只想将子模块更新为最新的提交而不是拉出所有提交。这可能吗?

例如,当我做

git submodule update --init --recursive

所有提升子模块都会被提取所有提交。我是否可以只要求子模块镜像最新的提交而不是拉动所有更改?

注意带有--depth标志的浅克隆不起作用,因为它只提取最新提交,而最新提交只包含在该提交中所做的更改,因此存储库不是处于正确的状态。

注意 git archive(如下面的答案所示)在我尝试以下命令序列时似乎不起作用

mkdir temp-git-test
cd temp-git-test
git init
git submodule add --depth 1 https://github.com/boostorg/boost
cd boost
git archive --format=tar HEAD --output ../boost.tar.gz
cd ..
tar -xzvf boost.tar.gz

解压缩仓库的输出与子模块相同。我做错了吗?

2 个答案:

答案 0 :(得分:6)

简短的回答是否定的。答案可能很长,但考虑另一种方式。

浅克隆和浅亚模块

很长的答案,让你可以获得你想要的东西,从一个技术说明开始:你用Git术语。在Git," pull"意味着"获取,然后合并或重组"而且你不会在这里合并或改变。事实上,当你进行初始化时,你通常会制作初始克隆。

每个子模块实际上都是它自己的存储库。 1 Git迟早会在每个存储库中执行git checkout,要求它检出,而不是< em> branch ,而是一个特定的提交,这通常最新的提交。鉴于Git存储库和软件开发的性质,以及子模块首先是对第三方存储库的引用的想法,即,您明确地不能控制,你可以做的最好的事情是:&#34;我知道我的软件可以与他们软件的一个特定版本一起使用,那个版本是&lt;填空白&gt;。&#34;因此,您的存储库会列出您希望从其存储库中获取的特定版本。

现在我们了解问题的核心。当您git clone存储库或使用git fetch更新现有克隆时,您可以通过询问特定的分支和/或标记名称而不是特定的提交ID来实现。获取特定ID有一些(非常有限的)支持,但必须在另一个存储库中启用它,我们刚刚说过你没有并且无法控制的存储库。对于他们来说,启用ID提取计算成本很高 - 无论他们&#34;他们&#34;是,控制其他存储库的那些 - 而不是你可以做的事情,也不是要求,也不是默认启用。这意味着一般来说它不可用。

在任何情况下,git clone 使用名称:例如,您可以git clone -b branch url通过检查特定分支来启动新克隆,或{ {1}}通过签出(作为分离的HEAD)特定标记来启动新克隆。尽管如此&#34;检查特定的分支或标签&#34;但是,克隆默认克隆远程提供的所有名称,并进行全深度(即非浅)克隆。

所有这些都意味着重要的事情。首先,浅克隆存在。浅层克隆是用git clone -b tag url参数制作的。它可以通过--depth与另一个git fetch加深。 &#34;深度&#34;是提取的提交数量超过&#34;由克隆或获取期间使用的名称标识的提交,以及一些相当复杂的规则。 (这些规则的细节在这里并不重要。)

其次,由于存在浅层克隆,浅层子模块也存在。浅层子模块只是一个用--depth克隆的子模块。但是存在一个问题:没有简单或明显的方法来确定需要的深度。您可以将--depth参数传递给--depthgit submodule add,但是你应该走多远并不明显。

问题在于:您的子模块将被克隆,可能是通过分支或标记名称进行克隆,但是您的子模块将被告知签出一个特定的提交(通过其原始哈希) ID)。这个提交会在克隆中吗?什么深度保证它会?如果您按标记名称进行克隆,并且标记始终指定正确的提交,则可以使用git submodule update(因此您可以在初始--depth 1期间使用--shallow-submodules),但是只有如果,嗯,见上文。

1 这些子存储库的特殊之处在于它们是:

  1. 列在外部存储库中(在git clone文件中);
  2. 一般保持在&#34;分离的HEAD&#34;模式;
  3. 并在ID存储在外部存储库中的提交中分离。
  4. 模块文件列出了各个子模块的名称和URL。 &#34;初始化&#34;子模块相当于将内容从.gitmodules复制到包含超级项目的配置文件中,并且&#34;更新&#34;子模块通常相当于克隆或获取。子模块将被分离的提交被记录在超级项目的存储库中作为&#34; gitlink&#34;在树对象中输入。

    在现代版本的Git中,子模块支持变得相当复杂,所以现在在执行更新步骤时可以做更多的事情。

    参考克隆

    对于许多情况,有一个更好,更通用的解决方案。您可以将Git指向引用克隆,而不是使用浅层克隆。参考克隆是您尝试克隆的存储库的任何克隆。 2 理想情况下,它是最新且合理的最新克隆您正在克隆的存储库,但任何克隆都可以。

    Git对引用克隆的作用有点复杂(详见the documentation),但简短版本是克隆某些存储库时,而不是从某个远程服务器通过网络获取所有对象(这可能是缓慢的和/或速率有限的),你的Git会向远程服务器询问它需要什么对象,然后查看 local 3 参考克隆来查看如果已经那些对象。如果是这样,它将&#34;借用&#34;他们来自参考克隆。

    这使您可以在使用非常少的网络和存储资源的同时获得完整,完整,最新的克隆,因为您不再需要(大部分或全部)数据,也不需要(除非{{ 1}} - ing)自己存储。这反过来意味着您不必担心您的浅层克隆浅:您只需获得一个缓慢的完整克隆,然后引用其中所有其他克隆的快速克隆。 使用引用克隆可以缩短克隆几个大GitHub存储库的时间,例如从一小时以上到几十秒。

    2 从技术上讲,引用可以是任何存储库。但是,与您正在克隆的存储库实际上没有关联的存储库将会成为一个糟糕的引用:它将具有您需要的对象的 none ,并且根本不提供加速。 (它甚至可能在对象的名称下有错误的数据,虽然它的可能性很小。如果引用 正确,则不会发生这种情况,因为对象名称不能以这种方式重用。 )

    3 参考应该是#34;尽可能在本地&#34;速度,但不一定要在你的机器上,只需可访问。如果引用并不总是存在,您可能希望添加.gitmodules,以便将对象从引用克隆复制到新克隆中。当然,这会占用更多的磁盘空间。

答案 1 :(得分:5)

  

注意带有--depth标志的浅层克隆不起作用,因为它只会提取最新的提交,而最新的提交只包含在该提交中所做的更改,因此存储库未处于正确的状态。

然后将boost个repo的 git archive 与您的子模块的浅克隆设置合并:

  • 您的子模块仍然很浅
  • 但是你用同一个仓库的git archive图像的一个(完整的)覆盖其不完整的内容,使工作树成为远程仓库SHA1的精确副本。

从那里,每次刷新(浅)都将补充一个完整的内容,并将保持最新。

git archive在repo的本地克隆中完成:

git archive --format=tar HEAD

如果您没有本地克隆,但是增强仓库在GitHub上(例如,boostorg/boost),那么您可以获得当前HEAD {{3}的压缩图像(不需要git archive)。

如评论中所示,添加存档的内容是没有用的,因为它代表了提交的相同内容。

然而,这似乎不完整:

git submodule add --depth 1 https://github.com/boostorg/boost

对于子模块更新 - 远程工作(即获取最后提交,而不是保持初始SHA1签出),您需要:

git submodule add -b master --depth 1 https://github.com/boostorg/boost

然后git submodule update --init --recursive --remote将获取最后一次提交。

请参阅&#34; with a simple curl&#34;。