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
- Create new repository and add remote
git init - Enable sparse checkout
git config core.sparsecheckout true This command enables the necessary sparse-checkout config settings
- Specify directories To specify directories, edit file "sparse-checkout" inside directory
.git/infoby adding directory path per line, like so:
dir-in-root another-dir-in-root/sub-dir 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 - Add the remote To add remote, run:
git remote add -f <name> The -f flag will cause git to run git fetch <name> after remote information is set.
- Pull files To pull files run:
git pull <name> <branch> 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 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 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-tagscan 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> 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> 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 While manually removing the first line, end leaving "sparse-checkout" like:
!Generators contrib/emacs/* And running:
git reset --hard <remote-name>/<branch> Resulted in:
example: contrib example/contrib: emacs example/contrib/emacs: README git-blame.el git.el Note!
I am not aware of any problemsgit resetmay cause but it is a functionality I haven't fully tested for a meaningful amount of time.
Top comments (0)