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/info
by 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-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>
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 reset
may cause but it is a functionality I haven't fully tested for a meaningful amount of time.
Top comments (0)