Search code examples
gitgit-submodulesgit-sparse-checkout

How to do submodule sparse-checkout with Git?


There are a lot of articles and SO questions about sparse-checkout. Unfortunately I did not find concrete examples. I would like to get this following example work:

Create a submodule

cd ~
mkdir sub && cd $_
git init 
mkdir foo && touch $_/foo
mkdir bar && touch $_/bar
git add .
git commit -am "Initial commit"

Create a project

cd ~
mkdir project && cd $_
git init
git submodule add ../sub sub
git config -f .gitmodules submodule.sub.shallow true
git config -f .gitmodules submodule.sub.sparsecheckout true
echo foo/* > .git/modules/sub/info/sparse-checkout
git commit -am "Initial commit"
git submodule update
cd sub
git checkout .

A this point I am expecting sub folder to only contain foo/foo not bar. Unfortunately it doesn't work:

$ ls
bar/ foo/

How can I make it work?


Solution

  • git submodule add itself checks out the submodule.

    What succeeded for me was:

    git init
    # I did not find a way to add submodule in 1 step without checking out
    git clone --depth=1 --no-checkout ../sub sub
    git submodule add ../sub sub
    git submodule absorbgitdirs
    # note there is no "submodule.sub.sparsecheckout" key
    git -C sub config core.sparseCheckout true
    # note quoted wildcards to avoid their expansion by shell
    echo 'foo/*' >>.git/modules/sub/info/sparse-checkout
    git submodule update --force --checkout sub
    

    Or from a git URL:

    # Initialize main repo (if needed)
    git init
    
    # Checkout the to-be submodule
    # I did not find a way to add submodule in 1 step without checking out
    git clone --depth=1 --no-checkout [email protected]:username/some-repo.git path/some-repo
    
    # Add as a submodule
    git submodule add [email protected]:username/some-repo.git path/some-repo
    
    # Move the .git dir from path/some-repo/.git into parent repo's .git 
    git submodule absorbgitdirs
    
    # Note there is no "submodule.sub.sparsecheckout" key
    git -C sub config core.sparseCheckout true
    
    # This pattern determines which files within some-repo.git get checked out. 
    # Note quoted wildcards to avoid their expansion by shell
    echo 'foo/*'  >> .git/modules/path/some-repo/info/sparse-checkout
    
    # Actually do the checkout
    git submodule update --force --checkout sub