如何制作浅的 git 子模块?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2144406/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to make shallow git submodules?
提问by Mauricio Scheffer
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-submoduleto implement this?
我应该hack git-submodule来实现这个吗?
采纳答案by VonC
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
.
See the end of this answer)
(并且 git 2.10 Q3 2016 允许用 记录它git config -f .gitmodules submodule.<name>.shallow true
。
请参阅此答案的结尾)
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. 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
<[email protected]>
Acked-by: Jens Lehmann<[email protected]>
将
--depth
选项添加到“git submodule”的添加和更新命令中,然后传递给克隆命令。当子模块很大并且除了最新提交之外你对任何东西都不感兴趣时,这很有用。添加了测试并进行了一些缩进调整以符合测试文件的其余部分“子模块更新可以处理密码中的符号链接”。
签字人:Fredrik Gustafsson
<[email protected]>
认可人:Jens Lehmann<[email protected]>
That means this works:
这意味着这有效:
git submodule add --depth 1 -- repository path
git submodule update --depth -- [<path>...]
With:
和:
--depth::
This option is valid for
add
andupdate
commands.
Create a 'shallow' clone with a history truncated to the specified number of revisions.
此选项对
add
和update
命令有效。
创建一个“浅”克隆,其历史记录被截断为指定数量的修订。
atwymanadds in the comments:
As far as I can tell this option isn't usable for submodules which don't track
master
very closely. If you set depth 1, thensubmodule update
can only ever succeed if the submodule commit you want is the latest master. Otherwise you get "fatal: reference is not a tree
".
据我所知,此选项不适用于跟踪不是
master
很紧密的子模块。如果你设置深度 1,那么submodule update
只有当你想要的子模块提交是最新的主模块时才能成功。 否则你会得到“fatal: reference is not a tree
”。
That is true.
That is, until git 2.8 (March 2016). 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.
那是真实的。
也就是说,直到 git 2.8(2016 年 3 月)。使用 2.8,submodule update --depth
即使 SHA1 可以从远程存储库 HEAD 之一直接访问,它也有一次成功的机会。
See commit fb43e31(24 Feb 2016) by Stefan Beller (stefanbeller
).
Helped-by: Junio C Hamano (gitster
).
(Merged by Junio C Hamano -- gitster
--in commit 9671a76, 26 Feb 2016)
请参阅Stefan Beller ( ) 的提交 fb43e31(2016 年 2 月 24 日)。
帮助者:Junio C Hamano ( )。(由Junio C Hamano合并-- --在提交 9671a76 中,2016 年 2 月 26 日)stefanbeller
gitster
gitster
submodule: try harder to fetch needed sha1 by direct fetching 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.
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.If
$sha1
was not part of the default fetch, we try to fetch the$sha1
directly. Some servers however do not support direct fetch by sha1, which leadsgit-fetch
to fail quickly.
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 更努力地获取所需的 sha1
在同时更新 Gerrit 中的子模块的更改时,常见的做法是在本地下载并挑选补丁进行测试。
但是,在本地测试时,“git submodule update
”可能无法获取正确的子模块 sha1,因为子模块中的相应提交还不是项目历史的一部分,而只是提议的更改。如果
$sha1
不是默认获取的一部分,我们尝试$sha1
直接获取. 但是有些服务器不支持sha1直接获取,这会导致git-fetch
快速失败。
我们可以在这里失败,因为仍然缺少的 sha1 无论如何都会导致稍后在结帐阶段失败,所以在这里失败是我们所能得到的。
MVGpoints out in the commentsto commit fb43e31(git 2.9, Feb 2016)
MVG指出,在评论中,以提交fb43e31(GIT 2.9 2月2016)
It would seem to me that commit fb43e31requests the missing commit by SHA1 id, so the
uploadpack.allowReachableSHA1InWant
anduploadpack.allowTipSHA1InWant
settings on the server will probably affect whether this works.
I wrote a post 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.
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.
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.
在我看来,提交 fb43e31请求 SHA1 id 丢失的提交,因此服务器上的
uploadpack.allowReachableSHA1InWant
和uploadpack.allowTipSHA1InWant
设置可能会影响这是否有效。
我今天在 git list 上写了一篇文章,指出如何使用浅子模块在某些情况下更好地工作,即如果提交也是一个标签。
让我们等着看。我想这就是 fb43e31 将特定 SHA1 的提取作为默认分支提取后的回退的原因。
尽管如此,在“--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
).
(Merged by Sebastian Schuberth -- sschuberth
--in commit 8d3047c, 20 Apr 2017)
Git 2.13(2017 年第二季度)确实添加了Sebastian Schuberth ( ) 的提交 8d3047c(2017 年 4 月 19 日)。(由Sebastian Schuberth合并-- --在提交 8d3047c 中,2017 年 4 月 20 日)sschuberth
sschuberth
a clone of this submodule will be performed as a shallow clone (with a history depth of 1)
此子模块的克隆将作为浅克隆执行(历史深度为 1)
However, fxscadds in the comments(and details in his answer)
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 putbranch = mybranch
on the.gitmodules
as well.
shallow = true
on.gitmodules
仅影响使用时远程 HEAD 跟踪的引用--recurse-submodules
,即使目标提交是由分支指向的,即使您也穿上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 季度)改进了子模块支持,该支持已更新为在工作树中缺少文件HEAD:.gitmodules
时从 blob 中读取.gitmodules
。
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
).
(Merged by Junio C Hamano -- gitster
--in commit abb4824, 13 Nov 2018)
见提交2b1257e,提交76e9bdc(2018年10月25日),并提交b5c259f,提交23dd8f5,提交b2faad4,提交2502ffc,提交996df4d,提交d1b13df,提交45f5ef3,提交bcbc780(2018年10月5日),由安东尼奥Ospite( )ao2
。
(由Junio C gitster
Hamano合并-- --在abb4824 提交中,2018 年 11 月 13 日)
submodule
: support reading.gitmodules
when it's not in the working treeWhen the
.gitmodules
file is not available in the working tree, try using the content from the index and from the current branch.
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 readthegitmodules
configuration file without fully populating the working tree.Writing to
.gitmodules
will still require that the file is checked out, so check for that before callingconfig_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; this prevents the command from leaving the repository in a spurious state (e.g. the submodule repository was cloned but.gitmodules
was not updated becauseconfig_set_in_gitmodules_file_gently
failed).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.
Currently this only happens inbuiltin/grep.c::grep_submodules()
, so callgrep_read_lock()
before invoking code involvingconfig_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.
submodule
:.gitmodules
当它不在工作树中时支持阅读当
.gitmodules
文件在工作树中不可用时,尝试使用来自索引和当前分支的内容。
这涵盖了文件是存储库的一部分但由于某种原因未检出的情况,例如由于稀疏检出。这使得它可以至少使用“
git submodule
这”命令读取的gitmodules
配置文件,而无需完全填充的工作树。写入
.gitmodules
仍然需要检出文件,因此在调用config_set_in_gitmodules_file_gently
.添加一个类似的检查,
git-submodule.sh::cmd_add()
以预测“git submodule add
”命令在.gitmodules
不可安全写入时的最终失败;这可以防止命令使存储库处于虚假状态(例如,子模块存储库被克隆但.gitmodules
由于config_set_in_gitmodules_file_gently
失败而未更新)。此外,由于
config_from_gitmodules()
现在访问全局对象存储,因此有必要保护调用该函数的所有代码路径以防止并发访问全局对象存储。
目前这只发生在builtin/grep.c::grep_submodules()
,所以grep_read_lock()
在调用涉及config_from_gitmodules()
.注意:在一种罕见的情况下,此新功能还不能正常工作:嵌套子模块不在
.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
).
(Merged by Junio C Hamano -- gitster
--in commit 678a9ca, 09 Oct 2019)
请参阅Ali Utku Selen ( ) 的commit ddb3c85(2019 年 9 月 30 日)。(由Junio C Hamano合并-- --在提交 678a9ca,2019 年 10 月 9 日)auselen
gitster
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
).
(Merged by Junio C Hamano -- gitster
--in commit ef61045, 05 Dec 2019)
请参阅Philippe Blain ( ) 的提交 f0e58b3(2019 年 11 月 24 日)。(由Junio C Hamano合并-- --在ef61045 提交中,2019 年 12 月 5 日)phil-blain
gitster
doc
: mention that 'git submodule update' fetches missing commitsHelped-by: Junio C Hamano
Helped-by: Johannes Schindelin
Signed-off-by: Philippe Blain'
git submodule
update' will fetch new commits from the submodule remote if the SHA-1 recorded in the superproject is not found. This was not mentioned in the documentation.
doc
:提到“git submodule update”获取丢失的提交帮助者:Junio C Hamano
帮助者:Johannes Schindelin
签字人:Philippe Blain如果未找到超级项目中记录的 SHA-1,'
git submodule
update'将从子模块远程获取新提交。这在文档中没有提到。
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
).
(Merged by Junio C Hamano -- gitster
--in commit 5dd1d59, 10 Dec 2019)
请参阅Jonathan Tan ( ) 的commit 4f3e57e和commit 10c64a0(2019 年 12 月 2 日)。(由Junio C Hamano合并-- --在5dd1d59 提交中,2019 年 12 月 10 日)jhowtan
gitster
submodule--helper
: advise on fatal alternate errorSigned-off-by: Jonathan Tan
Acked-by: Jeff KingWhen recursively cloning a superproject with some shallow modules defined in its
.gitmodules
, then recloning with "--reference=<path>
", an error occurs. 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--helper
: 关于致命的替代错误的建议签字人:Jonathan Tan
签字人:Jeff King当递归克隆一个在其 中定义了一些浅层模块的超级项目
.gitmodules
,然后用“--reference=<path>
”重新克隆时,会发生错误。例如: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
失败:
fatal: submodule '<snip>' cannot add alternate: reference repository '<snip>' is shallow
当无法添加从超级项目的替代项计算的替代项时,无论是在这种情况下还是其他情况,建议在克隆时配置“
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.alternateErrorStrategySigned-off-by: Jonathan Tan
Acked-by: Jeff KingCommit 31224cbdc7("
clone
: recursive and reference option triggers submodule alternates", 2016-08-17, Git v2.11.0-rc0 -- mergelisted in batch #1) taught Git to support the configuration options "submodule.alternateLocation
" and "submodule.alternateErrorStrategy
" on a superproject.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.The "
submodule.alternateErrorStrategy
" option determines what happens if that alternate cannot be referenced.
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).
Therefore, document it accordingly.
Doc
: 解释 submodule.alternateErrorStrategy签字人:Jonathan Tan
签字人:Jeff King提交31224cbdc7(“
clone
:递归和引用选项触发子模块替代”,2016 年 8 月 17 日,Git v2.11.0-rc0 --合并在批处理 #1 中列出)教导 Git 支持超级项目上的配置选项“submodule.alternateLocation
”和“submodule.alternateErrorStrategy
” .如果在超级项目上将“
submodule.alternateLocation
”配置为“superproject
”,则无论何时克隆该超级项目的子模块,它都会从超级项目中计算该子模块的类似替代路径$GIT_DIR/objects/info/alternates
,并引用它。"
submodule.alternateErrorStrategy
" 选项确定如果无法引用该替代项会发生什么情况。
但是,当该选项未设置为“死”时,克隆是否会像未指定替代项一样继续进行(如31224cbdc7中的测试所示),这一点尚不清楚。
因此,相应地记录它。
The config submodule documentationnow includes:
在配置子模块文档现在包括:
submodule.alternateErrorStrategy::
Specifies how to treat errors with the alternates for a submodule as computed via
submodule.alternateLocation
.
Possible values areignore
,info
,die
.
Default isdie
.
Note that if set toignore
orinfo
, and if there is an error with the computed alternate, the clone proceeds as if no alternate was specified.
submodule.alternateErrorStrategy::
指定如何处理通过子模块计算的替代项的错误
submodule.alternateLocation
。
可能的值为ignore
、info
、die
。
默认为die
。
请注意,如果设置为ignore
orinfo
,并且如果计算出的替代品有错误,则克隆继续进行,就好像没有指定替代品一样。
回答by KindDragon
回答by Mauricio Scheffer
Following Ryan's answerI 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
回答by Ryan Graham
Reading through the git-submodule "source", it looks like git submodule add
can handle submodules that already have their repositories present. In that case...
通读 git-submodule “source”,它看起来git submodule add
可以处理已经存在其存储库的子模块。在这种情况下...
$ 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
回答by Chris Johnsen
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. Manually clone the repositories so that they are shallow. If you think it would be useful, adapt git submodule
to support it. Send an email to the listasking 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.
如果您希望浅克隆来节省本地磁盘空间,那么 Ryan Graham 的答案似乎是一个不错的方法。手动克隆存储库,使它们变浅。如果您认为它有用,请适应git submodule
支持它。向列表发送一封电子邮件,询问它(实现它的建议、界面建议等)。在我看来,那里的人们非常支持那些热切希望以建设性方式增强 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 (e.g. make --mirror
clones of the canonical submodule repositories, then use --reference
in your submodules to point to these local clones). Just be sure to read about git clone --reference
/git clone --shared
before using --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
如果你确定有做每个子模块的一个完整克隆(加上后来取,让他们最新的),你可以尝试使用--reference
的选项git submodule update
(这是在Git的1.6.4或更高版本)来引用本地对象存储(例如,制作--mirror
规范子模块存储库的克隆,然后--reference
在您的子模块中使用以指向这些本地克隆)。请务必在使用之前阅读git clone --reference
/ 。引用镜像唯一可能的问题是它们是否最终获取非快进更新(尽管您可以启用引用日志并扩展它们的过期窗口以帮助保留任何可能导致问题的放弃提交)。你应该没有任何问题,只要git clone --shared
--reference
- 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. 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
. 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).
或者,--reference
您可以将镜像克隆与默认硬链接功能结合使用git clone
,使用本地镜像作为子模块的源。在新的超级项目克隆中,执行git submodule init
,编辑子模块 URL.git/config
指向本地镜像,然后执行git submodule update
. 您需要重新克隆任何现有的检出子模块以获取硬链接。您只需将一次下载到镜像中,然后从这些镜像本地获取到您检出的子模块中,就可以节省带宽。硬链接将节省磁盘空间(尽管获取会在多个检出子模块的对象存储实例中累积和复制;您可以定期从镜像中重新克隆检出子模块以重新获得由硬链接)。
回答by sfossen
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/([^^]+).*$||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
回答by Beeno Tung
Reference to How to clone git repository with specific revision/changeset?
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
回答by noabody
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]+).*/:/'); 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
. I use perl to concatenate this information, delimited by a colon, then employ variable transformation to separate the values into mysha
and mysub
.
git submodule
检索 40 个字符 sha1 后跟对应于.gitmodules
. 我使用 perl 连接这些信息,用冒号分隔,然后使用变量转换将值分隔为mysha
和mysub
。
These are the critical keys because we need the sha1 to download and the path to correlate the url
in .gitmodules.
这些是关键的键,因为我们需要下载 sha1 和关联url
.gitmodules的路径。
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. 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 .
.
myurl
键path =
然后查看 2 行后获取值。此方法可能无法始终如一地工作,需要改进。url grep.git
通过匹配最后一个/
和任何直到 a 的内容来去除任何剩余的类型引用.
。
mydir
is mysub
minus a final /name
which would by the directory leading up to the submodule name.
mydir
是mysub
减去最终/name
这将由领导到子模块名称的目录。
Next is a wget
with the format of downloadable zip archive url. This may change in future.
接下来是一个wget
可下载的 zip 存档 url 格式。这在未来可能会改变。
Unzip the file to mydir
which would be the subdirectory specified in the submodule path. The resultant folder will be the last element of the url
-sha1
.
将mydir
子模块路径中指定的子目录解压缩到的文件。所得到的文件夹将是最后一个元素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. When it works, the result is a shallow clone of a submodule at a specified changeset.
这更像是概念的 WIP 证明,而不是解决方案。当它工作时,结果是在指定变更集的子模块的浅克隆。
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.
像这样的脚本唯一有用的时候是源项目的非协作本地构建。