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?
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 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.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 ofgit 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 aboutgit 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 asIf 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.Alternatively, instead of
--reference
, you could use the mirror clones in combination with the default hardlinking functionality ofgit clone
by using local mirrors as the source for your submodules. In new super-project clones, dogit submodule init
, edit the submodule URLs in.git/config
to point to the local mirrors, then dogit 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).New in the upcoming git1.8.4 (July 2013):
(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)
See commit 275cd184d52b5b81cb89e4ec33e540fb2ae61c1f:
That means this works:
With:
atwyman adds in the comments:
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.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)MVG points out in the comments to commit fb43e31 (git 2.9, Feb 2016)
Update August 2016 (3 years later)
With Git 2.10 (Q3 2016), you will be able to do
See "Git submodule without extra weight" for more.
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)However, Ciro Santilli adds in the comments (and details in his answer)
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.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)Reading through the git-submodule "source", it looks like
git submodule add
can handle submodules that already have their repositories present. In that case...You'll want to make sure the required commit is in the submodule repo, so make sure you set an appropriate --depth.
Edit: You may be able to get away with multiple manual submodule clones followed by a single update:
Summary of buggy / unexpected / annoying behaviour as of Git 2.14.1
shallow = true
in.gitmodules
only affectsgit clone --recurse-submodules
if theHEAD
of the remote submodule points to the required commit, even if the target commit is pointed to by a branch, and even if you putbranch = mybranch
on the.gitmodules
as well.Local test script. Same behaviour on GitHub 2017-11, where
HEAD
is controlled by the default branch repo setting: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
.Local test script. Same behaviour on GitHub:
I also asked on the mailing list: https://marc.info/?l=git&m=151863590026582&w=2 and the reply was:
TODO test:
allowReachableSHA1InWant
.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.
Git 2.9.0 support submodules shallow clone directly, so now you can just call: