Shallow clone with submodules in git, how to use p

2019-04-19 18:18发布

问题:

This question already has an answer here:

  • How to shallow clone a specific commit with depth 1? 4 answers

I know it's possible to have shallow submodules using the --depth option with git submodule update.

However, If I run

git submodule update --init --recursive --depth 1

on my project with several submodules, I get a fatal: reference is not a tree. So I've tried again with

git submodule update --init --recursive --depth 100

which worked correctly, however I'd like to keep depth at 1.

It seems to me that --depth 1 pulls the latest commit in the submodule, not the commit pointed by the main repository, and that's why setting it to 100 solved the problem, since it pulled a longer list of commits, including the pointed ones.

Unfortunately, if that's the case then I cannot generally be sure the latest 100 commits include the one I need.

How do I tell git to use the pointed commits and not the latest ones in the shallow clone with submodules?

I'm using git 1.9.4 on Windows.

回答1:

Unfortunately there doesn't seem to be a way to do a git fetch with only a specific commit ID. If there is I would really want to know. However I have dealt with your problem in two different ways: one, if it's possible, is to create a tag or branch on the remote repository which points to the commit I want, say we call it "ref". This way I can fetch the remote ref and the --depth will apply to it, not the latest tip. Instead of git submodule update --init I do:

git submodule init
git clone --depth 1 -b ref --separate-git-dir .git/modules/sub/ repository sub

where "sub" is the name and path of the submodule (for simplicity let's say they are the same)

The other way, if you can't create tags or branches in the remote repository, is to search for the commit you want in a loop:

git submodule init
id=$(git submodule status|sed -ne 's/.\([a-z0-9]*\) sub.*/\1/p'
git clone --depth 1 --separate-git-dir -n .git/modules/sub/ repository sub    
cd sub
while ! git rev-list $id ; do
    git fetch --depth $((i+=1))
done
git checkout $id

You could increment with more than just one commit at a time to make it go faster, but you might end up with some earlier commits than the one you want.