4

I have a submodule to be used with sparse checkout. Without sparse checkout I'd do

git submodule update --init <path/to/submodule>

but how to initialize the submodule repository empty without fetching it (or fetching it, but not checking it out) yet, so I can invoke

cd <path/to/submodule>
git config core.sparseCheckout true
cd <../../..>
echo <subdir-to-get> .git/modules/<path/to/submodule>/info/sparse-checkout

Unfortunately

git submodule init <path/to/submodule>

does not create the repository in .git/modules/<path/to/submodule> and the file <path/to/submodule>/.git.

Thomas S.
  • 5,804
  • 5
  • 37
  • 72

2 Answers2

9

You can try, as in here, to clone the submodule as normal repository first, and then use git submodule absorbgitdirs.

By cloning first with a depth of 1, you don't get too many data:

git clone --depth=1 --no-checkout an/Url <path/to/submodule>
git submodule add an/Url <path/to/submodule>
git submodule absorbgitdirs

Then, you can modify the .git/modules/<path/to/submodule>/info/sparse-checkout

git -C <path/to/submodule> config core.sparseCheckout true
echo 'foo/*' >>.git/modules/<path/to/submodule>/info/sparse-checkout

Finally, get only the files you want:

git submodule update --force --checkout <path/to/submodule>

As commented by Janus, one can do even better (fewer data) with a git clone --filter, which I illustrated in 2019 with "What is the git clone --filter option's syntax?":

#fastest clone possible:
git clone --filter=blob:none --no-checkout https://github.com/git/git
cd git
suburl=$(git config -f .gitmodules --get submodule.<sub>.url)
git submodule update --init --force --checkout <sub>

(Replace <sub> by the submodule name entry from your .gitmodules)

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • what is `git -C` I don't even see that documented. – Evan Carroll Jul 19 '20 at 16:37
  • 1
    @EvanCarroll But it is documented: https://git-scm.com/docs/git#Documentation/git.txt--Cltpathgt. Since 2013: https://stackoverflow.com/a/20115526/6309 – VonC Jul 19 '20 at 16:39
  • This is the most concise working answer for this problem I have found. A few extra pointers: If `depth=1` is still too much data, you can check out a tag at the initial commit with `git clone --branch initial ...`, alternatively you can use `--filter=blob:none`. Also, to get the URL of the repo, you can use `git config -f .\.gitmodules --get submodule..url` Finally, you can skip the `git submodule add` and instead use `git submodule update ---init --force --checkout sub` as the final step. – Janus Dec 15 '21 at 11:38
  • @Janus Thank you for this feedback. Could you review my last edit to this answer and correct it, if I have misunderstood your proposed sequence of commands? – VonC Dec 15 '21 at 13:24
  • Thanks for updating @VonC! Two small things: if you include the `--init` in the final `submodule update` (as you do now), it is ok to drop the `git submodule add` in the first code block. Also, the `.\.gitmodules` is windows gunk from me -- probably `.gitmodules` is more portable. – Janus Dec 15 '21 at 13:34
  • @Janus But for the `update --init` to works, it needs to find the URL in the `.gitmodules` file. Hence the `git submodule add`, no? – VonC Dec 15 '21 at 13:39
  • 1
    Ah, maybe we are looking at two different scenarios: I am trying to check out for a repo where .gitmodules is already populated – Janus Dec 16 '21 at 15:00
  • @Janus OK, makes sense. My answer might not apply to that scenario, I presume... – VonC Dec 16 '21 at 15:27
1

I'm trying using the below approaches, simplified from the other answer by VonC and community.

To init existing submodule using a filter:

git submodule update --init --filter=blob:none

To add submodule using a filter:

git clone --filter=blob:none sub/mod/url [submodpath]
git submodule add sub/mod/url [submodpath] # doesn't download
git submodule absorbgitdirs
fuzzyTew
  • 3,511
  • 29
  • 24