简体   繁体   English

如何制作浅的 git 子模块?

[英]How to make shallow git submodules?

Is it possible to have shallow submodules?是否可以有浅子模块? I have a superproject with several submodules, each with a long history, so it gets unnecessarily big dragging all that history.我有一个包含几个子模块的超级项目,每个子模块都有很长的历史,所以它不必要地拖着所有的历史。

All I have found is this unanswered thread .我发现的只是 这个未答复的线程

Should I just hack git-submodule to implement this?我应该hack git-submodule来实现这个吗?

New in the upcoming git1.8.4 (July 2013) :即将推出的git1.8.4(2013 年 7 月)中的新内容

" git submodule update " can optionally clone the submodule repositories shallowly. git submodule update ”可以选择浅层克隆子模块存储库。

(And git 2.10 Q3 2016 allows to record that with git config -f .gitmodules submodule.<name>.shallow true . (并且 git 2.10 Q3 2016 允许使用git config -f .gitmodules submodule.<name>.shallow true
See the end of this answer)请参阅此答案的结尾)

See commit 275cd184d52b5b81cb89e4ec33e540fb2ae61c1f :提交 275cd184d52b5b81cb89e4ec33e540fb2ae61c1f

Add the --depth option to the add and update commands of "git submodule", which is then passed on to the clone command.--depth选项添加到“git submodule”的添加和更新命令中,然后传递给克隆命令。 This is useful when the submodule(s) are huge and you're not really interested in anything but the latest commit.当子模块很大并且除了最新提交之外你对任何东西都不感兴趣时​​,这很有用。

Tests are added and some indention adjustments were made to conform to the rest of the testfile on "submodule update can handle symbolic links in pwd".添加了测试并进行了一些缩进调整以符合测试文件的其余部分“子模块更新可以处理密码中的符号链接”。

Signed-off-by: Fredrik Gustafsson <iveqy@iveqy.com>签字人:Fredrik Gustafsson <iveqy@iveqy.com>
Acked-by: Jens Lehmann <Jens.Lehmann@web.de>确认者:Jens Lehmann <Jens.Lehmann@web.de>

That means this works:这意味着这有效:

# add shallow submodule
git submodule add --depth 1 <repo-url> <path>
git config -f .gitmodules submodule.<path>.shallow true

# later unshallow
git config -f .gitmodules submodule.<path>.shallow false
git submodule update <path>

The commands can be ran in any order.命令可以按任何顺序运行。 The git submodule command perform the actual clone (using depth 1 this time). git submodule命令执行实际的克隆(这次使用深度 1)。 And the git config commands make the option permanent for other people who will clone the repo recursively later.并且git config命令使该选项对于稍后将递归克隆 repo 的其他人永久存在。

As an example, suppose you have the repo https://github.com/foo/bar and you want to add https://github.com/lorem/ipsum as a submodule, in your repo at path/to/submodule .例如,假设您有 repo https://github.com/foo/bar并且您想将https://github.com/lorem/ipsum作为子模块添加到您的 repo 中的path/to/submodule The commands may look like like the following:命令可能如下所示:

git submodule add --depth 1 git@github.com:lorem/ipsum.git path/to/submodule
git config -f .gitmodules submodule.path/to/submodule.shallow true

The following results in the same thing too (opposite order):以下结果也相同(相反的顺序):

git config -f .gitmodules submodule.path/to/submodule.shallow true
git submodule add --depth 1 git@github.com:lorem/ipsum.git path/to/submodule

The next time someone runs git clone --recursive git@github.com:foo/bar.git , it will pull in the whole history of https://github.com/foo/bar , but it will only shallow-clone the submodule as expected.下次有人运行git clone --recursive git@github.com:foo/bar.git ,它会拉入https://github.com/foo/bar的整个历史,但它只会浅克隆子模块如预期。

With:和:

--depth

This option is valid for add and update commands.此选项对addupdate命令有效。
Create a 'shallow' clone with a history truncated to the specified number of revisions.创建一个“浅”克隆,其历史记录被截断为指定数量的修订。


atwyman adds in the comments : atwyman 在评论中补充道:

As far as I can tell this option isn't usable for submodules which don't track master very closely.据我所知,此选项不适用于不能非常密切地跟踪master模块的子模块。 If you set depth 1, then submodule update can only ever succeed if the submodule commit you want is the latest master.如果您设置深度 1,则只有当您想要的子模块提交是最新的主模块时, submodule update才能成功。 Otherwise you get " fatal: reference is not a tree " .否则你会得到“ fatal: reference is not a tree

That is true.那是真实的。
That is, until git 2.8 (March 2016).也就是说,直到 git 2.8(2016 年 3 月)。 With 2.8, the submodule update --depth has one more chance to succeed, even if the SHA1 is directly reachable from one of the remote repo HEADs.在 2.8 中,即使 SHA1 可以从远程仓库 HEAD 之一直接访问, submodule update --depth也有一次成功的机会。

See commit fb43e31 (24 Feb 2016) by Stefan Beller ( stefanbeller ) .请参阅Stefan Beller ( stefanbeller ) 提交的 fb43e31 (24 Feb 2016 )
Helped-by: Junio C Hamano ( gitster ) .帮助者: Junio C gitster ( gitster )
(Merged by Junio C Hamano -- gitster -- in commit 9671a76 , 26 Feb 2016) (由Junio C gitster合并-- gitster -- in commit 9671a76 ,2016 年 2 月 26 日)

submodule: try harder to fetch needed sha1 by direct fetching sha1子模块:通过直接获取 sha1 更努力地获取所需的 sha1

When reviewing a change that also updates a submodule in Gerrit, a common review practice is to download and cherry-pick the patch locally to test it.在审查同时更新 Gerrit 中的子模块的更改时,常见的审查做法是在本地下载并挑选补丁进行测试。
However when testing it locally, the ' git submodule update ' may fail fetching the correct submodule sha1 as the corresponding commit in the submodule is not yet part of the project history, but also just a proposed change.但是,在本地测试时,“ git submodule update ”可能无法获取正确的子模块 sha1,因为子模块中的相应提交还不是项目历史的一部分,而只是提议的更改。

If $sha1 was not part of the default fetch, we try to fetch the $sha1 directly .如果$sha1不是默认提取的一部分,我们尝试直接提取$sha1 Some servers however do not support direct fetch by sha1, which leads git-fetch to fail quickly.但是有些服务器不支持通过 sha1 直接获取,这会导致git-fetch快速失败。
We can fail ourselves here as the still missing sha1 would lead to a failure later in the checkout stage anyway, so failing here is as good as we can get.我们可以在这里失败,因为仍然缺少的 sha1 无论如何都会导致稍后在结帐阶段失败,所以在这里失败是我们所能得到的。


MVG points out in the comments to commit fb43e31 (git 2.9, Feb 2016) MVG 在评论中指出提交 fb43e31 (git 2.9,2016年 2 月)

It would seem to me that commit fb43e31 requests the missing commit by SHA1 id, so the uploadpack.allowReachableSHA1InWant and uploadpack.allowTipSHA1InWant settings on the server will probably affect whether this works.在我看来, 提交 fb43e31通过 SHA1 id 请求丢失的提交,因此服务器上的uploadpack.allowReachableSHA1InWantuploadpack.allowTipSHA1InWant设置可能会影响这是否有效。
I wrote apost to the git list today , pointing out how the use of shallow submodules could be made to work better for some scenarios, namely if the commit is also a tag.今天在 git list 上写了一篇文章,指出如何使用浅子模块在某些情况下更好地工作,即如果提交也是一个标签。
Let's wait and see.让我们等着看。

I guess this is a reason why fb43e31 made the fetch for a specific SHA1 a fallback after the fetch for the default branch.我想这就是 fb43e31 将特定 SHA1 的提取作为默认分支提取后的回退的原因。
Nevertheless, in case of “--depth 1” I think it would make sense to abort early: if none of the listed refs matches the requested one, and asking by SHA1 isn't supported by the server, then there is no point in fetching anything, since we won't be able to satisfy the submodule requirement either way.尽管如此,在“--depth 1”的情况下,我认为提前中止是有意义的:如果列出的所有引用都与请求的引用都不匹配,并且服务器不支持 SHA1 请求,则没有意义获取任何东西,因为无论如何我们都无法满足子模块的要求。


Update August 2016 (3 years later) 2016 年 8 月更新(3 年后)

With Git 2.10 (Q3 2016), you will be able to do使用 Git 2.10(2016 年第三季度),您将能够做到

 git config -f .gitmodules submodule.<name>.shallow true

See " Git submodule without extra weight " for more.有关更多信息,请参阅“没有额外重量的 Git 子模块”。


Git 2.13 (Q2 2017) do add in commit 8d3047c (19 Apr 2017) by Sebastian Schuberth ( sschuberth ) . Git 2.13(2017 年第二季度)确实添加了Sebastian Schuberth ( sschuberth ) 提交的 8d3047c (2017 年 4 月 19 日
(Merged by Sebastian Schuberth -- sschuberth -- in commit 8d3047c , 20 Apr 2017) (由Sebastian Schuberth -- sschuberth --commit 8d3047c 中合并,2017 年 4 月 20 日)

a clone of this submodule will be performed as a shallow clone (with a history depth of 1)此子模块的克隆将作为浅克隆执行(历史深度为 1)

However, Ciro Santilli adds in the comments (and details in his answer )但是, Ciro Santilli 在评论中添加(以及他的回答中的详细信息)

shallow = true on .gitmodules only affects the reference tracked by the HEAD of the remote when using --recurse-submodules , even if the target commit is pointed to by a branch, and even if you put branch = mybranch on the .gitmodules as well. .gitmodules上的shallow = true仅影响使用--recurse-submodules时远程的 HEAD 跟踪的引用,即使目标提交是由分支指向的,即使您将branch = mybranch放在.gitmodules作为好。


Git 2.20 (Q4 2018) improves on the submodule support, which has been updated to read from the blob at HEAD:.gitmodules when the .gitmodules file is missing from the working tree. Git 2.20(2018 年第 4 季度)改进了子模块支持,当工作树中缺少.gitmodules文件时,子模块支持已更新为从HEAD:.gitmodules处的 blob 读取。

See commit 2b1257e , commit 76e9bdc (25 Oct 2018), and commit b5c259f , commit 23dd8f5 , commit b2faad4 , commit 2502ffc , commit 996df4d , commit d1b13df , commit 45f5ef3 , commit bcbc780 (05 Oct 2018) by Antonio Ospite ( ao2 ) .请参阅提交 2b1257e提交 76e9bdc (2018 年 10 月 25 日)和提交 b5c259f提交 23dd8f5提交b2faad4提交 2502ffc提交 996df4d提交 d1b13df提交 4820f5c ( Antonio 4520f5c ) 提交 4520f5c (2018 年 10 月 2018 ao2 )
(Merged by Junio C Hamano -- gitster -- in commit abb4824 , 13 Nov 2018) (由Junio C gitster合并gitsterabb4824 提交中,2018 年 11 月 13 日)

submodule : support reading .gitmodules when it's not in the working tree submodule :当它不在工作树中时支持读取.gitmodules

When the .gitmodules file is not available in the working tree, try using the content from the index and from the current branch..gitmodules文件在工作树中不可用时,尝试使用来自索引和当前分支的内容。
This covers the case when the file is part of the repository but for some reason it is not checked out, for example because of a sparse checkout.这涵盖了文件是存储库的一部分但由于某种原因未检出的情况,例如由于稀疏检出。

This makes it possible to use at least the ' git submodule ' commands which read the gitmodules configuration file without fully populating the working tree.这使得至少可以使用“ git submodule ”命令来读取gitmodules配置文件,而无需完全填充工作树。

Writing to .gitmodules will still require that the file is checked out, so check for that before calling config_set_in_gitmodules_file_gently .写入.gitmodules仍然需要检出文件,因此在调用config_set_in_gitmodules_file_gently之前检查它。

Add a similar check also in git-submodule.sh::cmd_add() to anticipate the eventual failure of the " git submodule add " command when .gitmodules is not safely writeable;git-submodule.sh::cmd_add()也添加一个类似的检查,以预测当.gitmodules不能安全写入时“ git submodule add ”命令的最终失败; this prevents the command from leaving the repository in a spurious state (eg the submodule repository was cloned but .gitmodules was not updated because config_set_in_gitmodules_file_gently failed).这可以防止命令使存储库处于虚假状态(例如,子模块存储库被克隆但.gitmodules未更新,因为config_set_in_gitmodules_file_gently失败)。

Moreover, since config_from_gitmodules() now accesses the global object store, it is necessary to protect all code paths which call the function against concurrent access to the global object store.此外,由于config_from_gitmodules()现在访问全局对象存储,因此有必要保护调用该函数的所有代码路径免受对全局对象存储的并发访问。
Currently this only happens in builtin/grep.c::grep_submodules() , so call grep_read_lock() before invoking code involving config_from_gitmodules() .目前这只发生在builtin/grep.c::grep_submodules() ,所以在调用涉及config_from_gitmodules()代码之前调用grep_read_lock() config_from_gitmodules()

NOTE: there is one rare case where this new feature does not work properly yet: nested submodules without .gitmodules in their working tree.注意:有一种罕见的情况,这个新特性还不能正常工作:在工作树中没有.gitmodules嵌套子模块。


Note: Git 2.24 (Q4 2019) fixes a possible segfault when cloning a submodule shallow.注意:Git 2.24(2019 年第四季度)修复了浅层克隆子模块时可能出现的段错误。

See commit ddb3c85 (30 Sep 2019) by Ali Utku Selen ( auselen ) .请参阅Ali Utku Selen ( auselen ) 提交的 ddb3c85 (2019 年 9 月 30 日)
(Merged by Junio C Hamano -- gitster -- in commit 678a9ca , 09 Oct 2019) (由Junio C gitster合并-- gitster -- in commit 678a9ca ,2019 年 10 月 9 日)


Git 2.25 (Q1 2020), clarifies the git submodule update documentation. Git 2.25(2020 年第一季度),阐明了git submodule update文档。

See commit f0e58b3 (24 Nov 2019) by Philippe Blain ( phil-blain ) .请参阅Philippe Blain ( phil-blain blain ) 提交的 f0e58b3 (2019 年 11 月 24 日
(Merged by Junio C Hamano -- gitster -- in commit ef61045 , 05 Dec 2019) (由Junio C gitster -- gitster --提交 ef61045 中合并,2019 年 12 月 5 日)

doc : mention that 'git submodule update' fetches missing commits doc : 提到“git submodule update”获取丢失的提交

Helped-by: Junio C Hamano帮助者:Junio C Hamano
Helped-by: Johannes Schindelin帮助者:约翰内斯·辛德林
Signed-off-by: Philippe Blain签字人:Philippe Blain

' git submodule update' will fetch new commits from the submodule remote if the SHA-1 recorded in the superproject is not found .如果未找到记录在超级项目中的 SHA-1, ' git submodule update'将从子模块远程获取新提交 This was not mentioned in the documentation.这在文档中没有提到。


Warning: With Git 2.25 (Q1 2020), the interaction between " git clone --recurse-submodules " and alternate object store was ill-designed.警告:在 Git 2.25(2020 年第一季度)中,“ git clone --recurse-submodules ”和备用对象存储之间的交互设计不当。

The documentation and code have been taught to make more clear recommendations when the users see failures.当用户看到失败时,文档和代码已经被教导来提出更明确的建议。

See commit 4f3e57e , commit 10c64a0 (02 Dec 2019) by Jonathan Tan ( jhowtan ) .请参阅Jonathan Tan ( jhowtan ) 的commit 4f3e57ecommit 10c64a0 (2019 年 12 月 2 日
(Merged by Junio C Hamano -- gitster -- in commit 5dd1d59 , 10 Dec 2019) (由Junio C gitster合并-- gitster -- in commit 5dd1d59 ,2019 年 12 月 10 日)

submodule--helper : advise on fatal alternate error submodule--helper :就致命的替代错误提供建议

Signed-off-by: Jonathan Tan签字人:Jonathan Tan
Acked-by: Jeff King确认者:杰夫·金

When recursively cloning a superproject with some shallow modules defined in its .gitmodules , then recloning with " --reference=<path> ", an error occurs.当递归克隆具有在其.gitmodules定义的一些浅层模块的超级.gitmodules ,然后使用“ --reference=<path> ”重新克隆时,会发生错误。 For example:例如:

 git clone --recurse-submodules --branch=master -j8 \\
  https://android.googlesource.com/platform/superproject \
  master
git clone --recurse-submodules --branch=master -j8 \
  https://android.googlesource.com/platform/superproject \
  --reference master master2

fails with:失败:

 fatal: submodule '<snip>' cannot add alternate: reference repository
'<snip>' is shallow

When a alternate computed from the superproject's alternate cannot be added, whether in this case or another, advise about configuring the " submodule.alternateErrorStrategy " configuration option and using " --reference-if-able " instead of " --reference " when cloning.当无法添加从超级项目的替代计算的替代时,无论是在这种情况下还是其他情况,建议在克隆时配置“ submodule.alternateErrorStrategy ”配置选项并使用“ --reference-if-able ”而不是“ --reference ” .

That is detailed in:这在:

With Git 2.25 (Q1 2020), The interaction between "git clone --recurse-submodules" and alternate object store was ill-designed.在 Git 2.25(2020 年第一季度)中,“git clone --recurse-submodules”和备用对象存储之间的交互设计不当。

Doc : explain submodule.alternateErrorStrategy Doc :解释 submodule.alternateErrorStrategy

Signed-off-by: Jonathan Tan签字人:Jonathan Tan
Acked-by: Jeff King确认者:杰夫·金

Commit 31224cbdc7 (" clone : recursive and reference option triggers submodule alternates", 2016-08-17, Git v2.11.0-rc0 -- merge listed in batch #1 ) taught Git to support the configuration options " submodule.alternateLocation " and " submodule.alternateErrorStrategy " on a superproject.提交31224cbdc7 (“ clone :递归和引用选项触发子模块替代”,2016 年 8 月 17 日,Git v2.11.0-rc0 -- 合并批处理 #1 中列出)教导 Git 支持配置选项“ submodule.alternateLocation ”和“ submodule.alternateErrorStrategy " 在一个超级项目上。

If " submodule.alternateLocation " is configured to " superproject " on a superproject, whenever a submodule of that superproject is cloned, it instead computes the analogous alternate path for that submodule from $GIT_DIR/objects/info/alternates of the superproject, and references it.如果在superproject上将“ submodule.alternateLocation ”配置为“ superproject ”,则无论何时克隆该超级项目的子模块,它都会从超级项目的$GIT_DIR/objects/info/alternates和引用中计算该子模块的类似替代路径它。

The " submodule.alternateErrorStrategy " option determines what happens if that alternate cannot be referenced. submodule.alternateErrorStrategy ”选项决定了如果无法引用该替代品会发生什么。
However, it is not clear that the clone proceeds as if no alternate was specified when that option is not set to "die" (as can be seen in the tests in 31224cbdc7 ).但是,当该选项未设置为“死”时,克隆是否会像未指定替代项一样继续进行(如31224cbdc7中的测试所示),这一点尚不清楚。
Therefore, document it accordingly.因此,相应地记录它。

The config submodule documentation now includes: 配置子模块文档现在包括:

 submodule.alternateErrorStrategy::

Specifies how to treat errors with the alternates for a submodule as computed via submodule.alternateLocation .指定如何处理通过submodule.alternateLocation计算的子模块的替代错误。
Possible values are ignore , info , die .可能的值是ignoreinfodie
Default is die .默认为die
Note that if set to ignore or info , and if there is an error with the computed alternate, the clone proceeds as if no alternate was specified .请注意,如果设置为ignoreinfo ,并且如果计算的替代项存在错误,则克隆继续进行,就像未指定替代项一样


Note: " git submodule update --quiet " ( man ) did not propagate the quiet option down to underlying git fetch ( man ) , which has been corrected with Git 2.32 (Q2 2021).注意:“ git submodule update --quiet( man )没有将 quiet 选项向下传播到底层git fetch ( man ) ,这已在 Git 2.32(2021 年第二季度)中得到纠正。

See commit 62af4bd (30 Apr 2021) by Nicholas Clark ( nwc10 ) .请参阅Nicholas Clark ( nwc10 ) 的commit 62af4bd (2021 年 4 月 30 日
(Merged by Junio C Hamano -- gitster -- in commit 74339f8 , 11 May 2021) (由Junio C gitster合并-- gitster -- in commit 74339f8 ,2021 年 5 月 11 日)

submodule update : silence underlying fetch with " --quiet " submodule update :使用“ --quiet ”静默底层获取

Signed-off-by: Nicholas Clark签字人:尼古拉斯·克拉克

Commands such as命令如

$ git submodule update --quiet --init --depth=1

involving shallow clones, call the shell function fetch_in_submodule, which in turn invokes git fetch .涉及浅克隆,调用 shell 函数fetch_in_submodule,它依次调用git fetch
Pass the --quiet option onward there.在那里传递--quiet选项。

Git 2.9.0直接支持子模块浅克隆,所以现在你可以调用:

git clone url://to/source/repository --recursive --shallow-submodules

Following Ryan's answer I was able to come up with this simple script which iterates through all submodules and shallow clones them:按照Ryan 的回答,我想出了这个简单的脚本,它遍历所有子模块并浅层克隆它们:

#!/bin/bash
git submodule init
for i in $(git submodule | sed -e 's/.* //'); do
    spath=$(git config -f .gitmodules --get submodule.$i.path)
    surl=$(git config -f .gitmodules --get submodule.$i.url)
    git clone --depth 1 $surl $spath
done
git submodule update

Reading through the git-submodule "source", it looks like git submodule add can handle submodules that already have their repositories present.通读 git-submodule “source”,看起来git submodule add可以处理已经存在其存储库的子模块。 In that case...在这种情况下...

$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
$ git submodule add $remotesub1 $sub1
#repeat as necessary...

You'll want to make sure the required commit is in the submodule repo, so make sure you set an appropriate --depth.您需要确保所需的提交位于子模块存储库中,因此请确保设置适当的 --depth。

Edit: You may be able to get away with multiple manual submodule clones followed by a single update:编辑:您可以使用多个手动子模块克隆,然后进行一次更新:

$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
#repeat as necessary...
$ git submodule update

Summary of buggy / unexpected / annoying behaviour as of Git 2.14.1自 Git 2.14.1 起的错误/意外/烦人行为摘要

  1. shallow = true in .gitmodules only affects git clone --recurse-submodules if the HEAD of the remote submodule points to the required commit, even if the target commit is pointed to by a branch, and even if you put branch = mybranch on the .gitmodules as well.如果远程子模块的HEAD指向所需的提交,则.gitmodules shallow = true仅影响git clone --recurse-submodules ,即使目标提交是由分支指向的,并且即使您将branch = mybranch放在.gitmodules也是如此。

    Local test script . 本地测试脚本 Same behaviour on GitHub 2017-11, where HEAD is controlled by the default branch repo setting: GitHub 2017-11 上的相同行为,其中HEAD由默认分支存储库设置控制:

     git clone --recurse-submodules https://github.com/cirosantilli/test-shallow-submodule-top-branch-shallow cd test-shallow-submodule-top-branch-shallow/mod git log # Multiple commits, not shallow.
  2. git clone --recurse-submodules --shallow-submodules fails if the commit is neither referenced by a branch or tag with a message: error: Server does not allow request for unadvertised object . git clone --recurse-submodules --shallow-submodules如果提交既没有被分支引用,也没有被带有消息的标记引用,则git clone --recurse-submodules --shallow-submodules失败: error: Server does not allow request for unadvertised object

    Local test script . 本地测试脚本 Same behaviour on GitHub: GitHub 上的相同行为:

     git clone --recurse-submodules --shallow-submodules https://github.com/cirosantilli/test-shallow-submodule-top-sha # error

    I also asked on the mailing list: https://marc.info/?l=git&m=151863590026582&w=2 and the reply was:我也在邮件列表上问过: https : //marc.info/? l =git&m=151863590026582&w=2 ,回复是:

    In theory this should be easy.理论上这应该很容易。 :) :)

    In practice not so much, unfortunately.不幸的是,实际上并没有那么多。 This is because cloning will just obtain the latest tip of a branch (usually master).这是因为克隆只会获得分支(通常是 master)的最新提示。 There is no mechanism in clone to specify the exact sha1 that is wanted. clone 中没有机制来指定所需的确切 sha1。

    The wire protocol supports for asking exact sha1s, so that should be covered.有线协议支持询问确切的 sha1,因此应该涵盖这一点。 (Caveat: it only works if the server operator enables uploadpack.allowReachableSHA1InWant which github has not AFAICT) (注意:只有服务器运营商启用了uploadpack.allowReachableSHA1InWant,github没有AFAICT,它才有效)

    git-fetch allows to fetch arbitrary sha1, so as a workaround you can run a fetch after the recursive clone by using "git submodule update" as that will use fetches after the initial clone. git-fetch 允许获取任意 sha1,因此作为一种解决方法,您可以使用“git submodule update”在递归克隆之后运行获取,因为这将在初始克隆后使用获取。

TODO test: allowReachableSHA1InWant . TODO 测试: allowReachableSHA1InWant

Are the canonical locations for your submodules remote?您的子模块的规范位置是否远程? If so, are you OK with cloning them once?如果是这样,你可以克隆它们一次吗? In other words, do you want the shallow clones just because you are suffering the wasted bandwidth of frequent submodule (re)clones?换句话说,您是否想要浅层克隆只是因为您正在遭受频繁子模块(重新)克隆浪费的带宽?

If you want shallow clones to save local diskspace, then Ryan Graham's answer seems like a good way to go.如果您希望浅克隆来节省本地磁盘空间,那么 Ryan Graham 的答案似乎是一个不错的方法。 Manually clone the repositories so that they are shallow.手动克隆存储库,使它们变浅。 If you think it would be useful, adapt git submodule to support it.如果您认为它有用,请调整git submodule以支持它。 Send an email to the list asking about it (advice for implementing it, suggestions on the interface, etc.).列表发送一封电子邮件,询问它(实现它的建议、界面建议等)。 In my opinion, the folks there are quite supportive of potential contributors that earnestly want to enhance Git in constructive ways.在我看来,那里的人们非常支持那些热切希望以建设性方式增强 Git 的潜在贡献者。

If you are OK with doing one full clone of each submodule (plus later fetches to keep them up to date), you might try using the --reference option of git submodule update (it is in Git 1.6.4 and later) to refer to local object stores (eg make --mirror clones of the canonical submodule repositories, then use --reference in your submodules to point to these local clones).如果你对每个子模块做一个完整的克隆(加上以后的获取以保持它们最新),你可以尝试使用git submodule update--reference选项(它在 Git 1.6.4 和更高版本中)来引用到本地对象存储(例如,制作规范子模块存储库的--mirror克隆,然后在子模块中使用--reference指向这些本地克隆)。 Just be sure to read about git clone --reference / git clone --shared before using --reference .在使用--reference之前,请务必阅读有关git clone --reference / git clone --shared --reference The only likely problem with referencing mirrors would be if they ever end up fetching non-fast-forward updates (though you could enable reflogs and expand their expiration windows to help retain any abandoned commits that might cause a problem).引用镜像唯一可能的问题是它们是否最终获取非快进更新(尽管您可以启用引用日志并扩展其过期窗口以帮助保留任何可能导致问题的放弃提交)。 You should not have any problems as long as你应该没有任何问题,只要

  • you do not make any local submodule commits, or您没有进行任何本地子模块提交,或者
  • any commits that are left dangling by non-fast-forwards that the canonical repositories might publish are not ancestors to your local submodule commits, or任何因规范存储库可能发布的非快进而悬而未决的提交都不是您本地子模块提交的祖先,或者
  • you are diligent about keeping your local submodule commits rebased on top of whatever non-fast-forwards might be published in the canonical submodule repositories.您努力保持本地子模块提交重新基于规范子模块存储库中可能发布的任何非快进。

If you go with something like this and there is any chance that you might carry local submodule commits in your working trees, it would probably be a good idea to create an automated system that makes sure critical objects referenced by the checked-out submodules are not left dangling in the mirror repositories (and if any are found, copies them to the repositories that need them).如果你采用这样的方法,并且有可能在你的工作树中携带本地子模块提交,那么创建一个自动化系统来确保被检出的子模块引用的关键对象不是一个好主意。留在镜像存储库中(如果有的话,将它们复制到需要它们的存储库中)。

And, like the git clone manpage says, do not use --reference if you do not understand these implications.而且,就像git clone联机帮助页所说的那样,如果您不理解这些含义,请不要使用--reference

# Full clone (mirror), done once.
git clone --mirror $sub1_url $path_to_mirrors/$sub1_name.git
git clone --mirror $sub2_url $path_to_mirrors/$sub2_name.git

# Reference the full clones any time you initialize a submodule
git clone $super_url super
cd super
git submodule update --init --reference $path_to_mirrors/$sub1_name.git $sub1_path_in_super
git submodule update --init --reference $path_to_mirrors/$sub2_name.git $sub2_path_in_super

# To avoid extra packs in each of the superprojects' submodules,
#   update the mirror clones before any pull/merge in super-projects.
for p in $path_to_mirrors/*.git; do GIT_DIR="$p" git fetch; done

cd super
git pull             # merges in new versions of submodules
git submodule update # update sub refs, checkout new versions,
                     #   but no download since they reference the updated mirrors

Alternatively, instead of --reference , you could use the mirror clones in combination with the default hardlinking functionality of git clone by using local mirrors as the source for your submodules.或者,您可以使用本地镜像作为子模块的源,而不是--reference ,将镜像克隆与git clone的默认硬链接功能结合使用。 In new super-project clones, do git submodule init , edit the submodule URLs in .git/config to point to the local mirrors, then do git submodule update .在新的超级项目克隆中,执行git submodule init ,编辑.git/config的子模块 URL 指向本地镜像,然后执行git submodule update You would need to reclone any existing checked-out submodules to get the hardlinks.您需要重新克隆任何现有的检出子模块以获取硬链接。 You would save bandwidth by only downloading once into the mirrors, then fetching locally from those into your checked-out submodules.您只需将一次下载到镜像中,然后从这些镜像本地获取到您检出的子模块中,就可以节省带宽。 The hard linking would save disk space (although fetches would tend to accumulate and be duplicated across multiple instances of the checked-out submodules' object stores; you could periodically reclone the checked-out submodules from the mirrors to regain the disk space saving provided by hardlinking).硬链接将节省磁盘空间(尽管提取会在多个检出子模块的对象存储实例中累积和复制;您可以定期从镜像中重新克隆检出的子模块,以重新获得由硬链接)。

I created a slightly different version, for when it's not running at the bleeding edge, which not all projects do.我创建了一个略有不同的版本,因为当它不在最前沿运行时,并非所有项目都这样做。 The standard submodule additions did't work nor did the script above.标准的子模块添加不起作用,上面的脚本也不起作用。 So I added a hash lookup for the tag ref, and if it doesn't have one, it falls back to full clone.所以我为标签引用添加了一个哈希查找,如果它没有,它会回退到完整的克隆。

#!/bin/bash
git submodule init
git submodule | while read hash name junk; do
    spath=$(git config -f .gitmodules --get submodule.$name.path)
    surl=$(git config -f .gitmodules --get submodule.$name.url)
    sbr=$(git ls-remote --tags $surl | sed -r "/${hash:1}/ s|^.*tags/([^^]+).*\$|\1|p;d")
    if [ -z $sbr ]; then
        git clone $surl $spath
    else
        git clone -b $sbr --depth 1 --single-branch $surl $spath
    fi
done
git submodule update 

Reference to How to clone git repository with specific revision/changeset?参考如何克隆具有特定修订版/变更集的 git 存储库?

I have written a simple script which has no problem when your submodule reference is away from the master我写了一个简单的脚本,当你的子模块引用远离主模块时它没有问题

git submodule foreach --recursive 'git rev-parse HEAD | xargs -I {} git fetch origin {} && git reset --hard FETCH_HEAD'

This statement will fetch the referenced version of submodule.此语句将获取子模块的引用版本。

It is fast but you cannot commit your edit on the submodule (you have to fetch unshallow it before https://stackoverflow.com/a/17937889/3156509 )它很快,但你不能在子模块上提交你的编辑(你必须在https://stackoverflow.com/a/17937889/3156509之前获取非浅层)

in full:在全:

#!/bin/bash
git submodule init
git submodule foreach --recursive 'git rev-parse HEAD | xargs -I {} git fetch origin {} && git reset --hard FETCH_HEAD'
git submodule update --recursive

Shallow clone of a submodule is perfect because they snapshot at a particular revision/changeset.子模块的浅克隆是完美的,因为它们在特定的修订/变更集上进行快照。 It's easy to download a zip from the website so I tried for a script.从网站下载 zip 很容易,所以我尝试了一个脚本。

#!/bin/bash
git submodule deinit --all -f
for value in $(git submodule | perl -pe 's/.*(\w{40})\s([^\s]+).*/\1:\2/'); do
  mysha=${value%:*}
  mysub=${value#*:}
  myurl=$(grep -A2 -Pi "path = $mysub" .gitmodules | grep -Pio '(?<=url =).*/[^.]+')
  mydir=$(dirname $mysub)
  wget $myurl/archive/$mysha.zip
  unzip $mysha.zip -d $mydir
  test -d $mysub && rm -rf $mysub
  mv $mydir/*-$mysha $mysub
  rm $mysha.zip
done
git submodule init

git submodule deinit --all -f clears the submodule tree which allows the script to be reusable. git submodule deinit --all -f清除允许脚本可重用的子模块树。

git submodule retrieves the 40 char sha1 followed by a path that corresponds to the same in .gitmodules . git submodule检索 40 个字符 sha1 后跟与.gitmodules相同的.gitmodules I use perl to concatenate this information, delimited by a colon, then employ variable transformation to separate the values into mysha and mysub .我使用 perl 连接这些信息,用冒号分隔,然后使用变量转换将值分成myshamysub

These are the critical keys because we need the sha1 to download and the path to correlate the url in .gitmodules.这些是关键的键,因为我们需要下载 sha1 以及关联 .gitmodules 中的url的路径。

Given a typical submodule entry:给定一个典型的子模块条目:

[submodule "label"]
    path = localpath
    url = https://github.com/repository.git

myurl keys on path = then looks 2 lines after to get the value. path =上的myurl键然后查找 2 行之后以获取值。 This method may not work consistently and require refinement.此方法可能无法始终如一地工作,需要改进。 The url grep strips any remaining .git type references by matching to the last / and anything up to a . url grep 通过匹配最后一个/和任何到.git类型的引用来.git任何剩余的.git类型引用. . .

mydir is mysub minus a final /name which would by the directory leading up to the submodule name. mydirmysub减去最终的/name ,该/name由通向子模块名称的目录组成。

Next is a wget with the format of downloadable zip archive url.接下来是一个wget ,格式为可下载的 zip 存档 url。 This may change in future.这在未来可能会改变。

Unzip the file to mydir which would be the subdirectory specified in the submodule path.将文件解压缩到mydir ,这将是子模块路径中指定的子目录。 The resultant folder will be the last element of the url - sha1 .结果文件夹将是url - sha1的最后一个元素。

Check to see if the subdirectory specified in the submodule path exists and remove it to allow renaming of the extracted folder.检查子模块路径中指定的子目录是否存在并将其删除以允许重命名提取的文件夹。

mv rename the extracted folder containing our sha1 to its correct submodule path. mv将包含我们 sha1 的提取文件夹重命名为其正确的子模块路径。

Delete downloaded zip file.删除下载的 zip 文件。

Submodule init子模块初始化

This is more a WIP proof of concept rather than a solution.这更像是概念的 WIP 证明,而不是解决方案。 When it works, the result is a shallow clone of a submodule at a specified changeset.当它工作时,结果是在指定变更集的子模块的浅克隆。

Should the repository re-home a submodule to a different commit, re-run the script to update.如果存储库将子模块重新归位到不同的提交,请重新运行脚本以进行更新。

The only time a script like this would be useful is for non-collaborative local building of a source project.像这样的脚本唯一有用的时候是源项目的非协作本地构建。

I needed a solution to shallow clone submodules when I can not effect on cloning of main repo.当我无法影响主 repo 的克隆时,我需要一个浅层克隆子模块的解决方案。 Based on one solution above:基于上述一种解决方案:

#!/bin/bash
git submodule init
for i in $(git submodule | sed -e 's/.* //'); do
    git submodule update --init --depth 1 -- $i
done

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM