DEV Community

Wojciech Rithaler
Wojciech Rithaler

Posted on

Sparse Checkout without command

Although not well known, there is a way to achieve git sparse-checkout on git versions before 2.26.0.

Acknowledgments

This, slightly more in-depth article was made possible thanks to the one written by Brian Coyner on his blog.

Sparse checkout

Sparse checkout is git's functionality that lets users pull remote repositories partially, saving time and space. It works by changing the working tree from having all files tracked to only those specified.

Availability

Nowadays the functionality is available thru it's own command git sparse-checkout since version 2.26.0 and, although experimental, it is the recommended way.

Unfortunately there are times and situations, especially in large corporations where "newest" version of git are not available.

Fortunately there are ways of achieving sparse checkout in older git versions.

Creating sparse checkout manually step by step

  1. Create new repository and add remote
   git init
Enter fullscreen mode Exit fullscreen mode
  1. Enable sparse checkout
   git config core.sparsecheckout true
Enter fullscreen mode Exit fullscreen mode

This command enables the necessary sparse-checkout config settings

  1. Specify directories To specify directories, edit file "sparse-checkout" inside directory .git/info by adding directory path per line, like so:
   dir-in-root
   another-dir-in-root/sub-dir
Enter fullscreen mode Exit fullscreen mode

The "sparse-checkout" file uses the same syntax as ".gitignore" file, therefor it is possible to specify the unwonted directories with !, for example:

   !unwonted-dir-name
Enter fullscreen mode Exit fullscreen mode
  1. Add the remote To add remote, run:
   git remote add -f <name>
Enter fullscreen mode Exit fullscreen mode

The -f flag will cause git to run git fetch <name> after remote information is set.

  1. Pull files To pull files run:
   git pull <name> <branch>
Enter fullscreen mode Exit fullscreen mode

The <name> must be the same name as the one provided in point 4.

Example

The example will use GitHub's git mirror to fetch directory "git/contrib/buildsystems" without it's subfolder "git/contrib/buildsystems/Generators".

git init
git config core.sparsecheckout true
echo contrib/buildsystems/* >> .git/info/sparse-checkout
echo !Generators >> .git/info/sparse-checkout
git remote add -f origin https://github.com/git/git.git
git pull origin master
Enter fullscreen mode Exit fullscreen mode

After running each line separately and running them as a single script, the result of command ls -R example was:

./example:
contrib

./example/contrib:
buildsystems

./example/contrib/buildsystems:
CMakeLists.txt  Generators.pm  engine.pl  generate  parse.pl
Enter fullscreen mode Exit fullscreen mode

Limitations

Git will not download actual files but will fetch information about the whole repo structure and tags.

There are ways of limiting what git will fetch:

  • --no-tags can be used to not download tags
  • --depth=<n> can be used to limit downloaded changes to to last "n" commits.

Adding or removing directory

Updating directories in "sparse-checkout" file will not automatically update local files. To update, a command git reset is required to be run like:

git reset --hard <remote-name>/<branch>
Enter fullscreen mode Exit fullscreen mode

git reset resets the branch to specified state.

--hard changes all the files in working tree to match the files in specified state.

Running:

echo contrib/emacs/* >> .git/info/sparse-checkout
git reset --hard <remote-name>/<branch>
Enter fullscreen mode Exit fullscreen mode

Resulted in:

example:
contrib

example/contrib:
buildsystems  emacs

example/contrib/buildsystems:
CMakeLists.txt  Generators.pm  engine.pl  generate  parse.pl

example/contrib/emacs:
README  git-blame.el  git.el
Enter fullscreen mode Exit fullscreen mode

While manually removing the first line, end leaving "sparse-checkout" like:

!Generators
contrib/emacs/*
Enter fullscreen mode Exit fullscreen mode

And running:

git reset --hard <remote-name>/<branch>
Enter fullscreen mode Exit fullscreen mode

Resulted in:

example:
contrib

example/contrib:
emacs

example/contrib/emacs:
README  git-blame.el  git.el
Enter fullscreen mode Exit fullscreen mode

Note!

I am not aware of any problems git reset may cause but it is a functionality I haven't fully tested for a meaningful amount of time.

Top comments (0)