git sparse-checkout
Tags: git, devjournal
Published: 2022-08-13 10:40:00

Yesterday, I discovered `git sparse-checkout` feature with @sanixdarker post

{% embed https://dev.to/sanixdarker/how-to-clone-a-sub-directory-of-a-git-project-not-a-zip-1kk7 %}

His article is good, and helped me to discover the feature.

Here I would like to log for archive what I found about `git sparse-checkout.`

## What is git sparse checkout

Here is what git documentation tells about it.

> Reduce your working tree to a subset of tracked files 

So if you have this kind of repository

```
README.md
CHANGELOG.md
src/
assests/
tests/
web/
tools
```

And you want to fetch only `src` and `tests` folders, use this.

```
src/
tests/
```

Because other folders are irrelevant to your needs.

## why would you need this ?

When running CI, you don't need assets (images, css ...) it could speed up the `git clone` on a huge repository

BUT you can add commit and work as normal. You simply didn't fetch the information of the other folders.

## Interesting reads

First, I've read this very interesting article

{% embed https://aymericbeaumet.com/faster-git-clones-with-sparse-checkouts %}

EDIT: you can also find an article on dev to from the author himself @aymericbeaumet {% embed https://dev.to/aymericbeaumet/faster-git-clones-with-sparse-checkouts-1ah %}



and of course the documentation https://www.git-scm.com/docs/git-sparse-checkout

## How to use it ?

### Start with a git clone minimal fetch

```bash
git clone --filter=blob:none --no-checkout <repository>
```

It's possible to configure a repository with nothing in it, **yet** (the yet is important)

*    `--filter=blob:none`: instructs not to fetch any blob object
*    `--no-checkout`: instructs not to automatically checkout HEAD

so here you can `git checkout` your branch, and it will bring nothing different from if you didn't use `--no-checkout`

but you can use `git sparse-checkout` instead.

### Sparse checkout

So remember, we only want `src` and `tests` folders.

So do this:

```bash
git sparse-checkout set src tests
```

{% collapsible Tips you can use --stdin %}

you can also use `--stdin`

```bash
echo -e "src\nassets" | git sparse-checkout set --stdin
```

Note: Here is used `echo` as an example, using `--stdin` means you are scripting your usage.

{% endcollapsible %}

Note: You can also add as you go or need

```bash
git sparse-checkout set src
# ...
# and later, even days later
git sparse-checkout add tests
# and here it would fetch the missing files
```

Note: You can also use `--stdin` with `git sparse-checkout add` also


{% collapsible Tips: use git sparse-checkout list to know what you are tracking %}

You can use `git sparse-checkout list` at any time to see what is configured.

```bash
git sparse-checkout list
```

```
src
tests
```

{% endcollapsible %}

{% collapsible How does git follow this internally %}

you can find the configured things in `.git/info/sparse-checkout` file

```
  /*
  !/*/
  /src/
  /tests/
```

Note: there are other files involved in sparse checkout, you can read the documentation. 

Warning: I would recommend to use `git sparse-checkout` command than playing with those files directly.

{% endcollapsible %}

## So what, then ?

well you can simply fetch and checkout your branch, only the requested folders or files will be present.

```
README.md
CHANGELOG.md
src/
tests/
whatever/
foobar/
```

```bash
git sparse-checkout set src tests
```

then if you check out the `main` branch, you will get this.

```bash
git checkout main
```

```
README.md
CHANGELOG.md
src/
tests/
```

Note: by default, all the files (files only, not folders) at the root of your repository will always be checkout. You can see the reason of this on the documentation.

if you don't want this, you will have to use a legacy feature via `--no-cone` parameter, when setting up your sparse checkout


```bash
git sparse-checkout set --no-cone src tests
```

then if you check out, you will get this.

```
src/
tests/
```

I hope you will find this useful.