1. Overview

Git comes with the option of trimming a repository’s working tree to only subdirectories or files – a feature called git sparse-checkout. This can come in handy when we only want to track specific files or subdirectories.

Besides git sparse-checkout, there are other ways to retrieve a subset of directories or files from a Git repository. In this tutorial, we’ll discuss different ways of cloning a git repository’s subdirectory.

2. Using git sparse-checkout

Before we proceed, we must state that, at the time of writing this tutorial, git sparse-checkout is experimental. So, there may be some irregularities in its behavior.

To clone a subdirectory using git sparse-checkout, we’ll git clone the directory first:

$ git clone --depth=1 https://github.com/Baeldung/stackify.git

The –depth=1 option ensures that the clone is limited to the most recent commits.

Next, we’ll cd into the local directory:

$ cd stackify

Then, we’ll check out to our desired subdirectory using git sparse-checkout set:

$ git sparse-checkout set tomcat-app

After running git sparse-checkout set, we’ll run ls -F to see the resources in the directory:

$ ls -F
pom.xml  README.md  tomcat-app/

As shown, our directory contains the tomcat-app subdirectory and its sibling files on checkout, even though we only specified tomcat-app. This happens because git sparse-checkout runs in cone mode by default.

In cone mode, sibling files and children resources are included in the checkout. But we can avoid this by executing the sparse checkout in –no-cone mode.

In –no-cone mode, git sparse-checkout commands read the arguments as patterns. So, if we wanted only the tomcat-app without its sibling files, we’ll pass a matching pattern:

$ git sparse-checkout set --no-cone tomcat-app

Using this new command, we checked out only the tomcat-app subdirectory in the root directory:

$ ls -F
tomcat-app/

However, if we had other resources named tomcat-app anywhere else in the working tree, the command would’ve included them in the sparse checkout. But we can also pass a pattern to limit that outcome:

$ git sparse-checkout set --no-cone tomcat-app/ '!*/tomcat-app'

The ‘!*/tomcat-app’ pattern directs the command to ignore any child resource named tomcat-app in the sibling subdirectories of the tomcat-app subdirectory:

$ ls -F
tomcat-app/

2.1. git sparse-checkout add

Running git sparse-checkout set over a previous git sparse-checkout set command will replace the initial tracked file or directory. So, if we want to add another subdirectory to the working tree, we’ll run git sparse-checkout add followed by the name of the subdirectory:

$ git sparse-checkout add webservices

Now, we have both the tomcat-app and the webservices subdirectories:

$ ls -F
tomcat-app/  webservices/

If we wanted to clone more than one directory or file at the start, we could’ve passed them all to git sparse-checkout set at once.

We can use git sparse-checkout on files, too. However, we may encounter unintended results when using it because the git sparse-checkout command is still experimental.

2.2. Disabling a Sparse Checkout

If we ever want to revert to a fully-tracked repository, we’ll run the disable command:

$ git sparse-checkout disable

With that, we’ll have all the files and repositories in our clone:

$ ls -F
core-java/    core-kotlin/  junit5-example/  logback-example/  pom.xml    remote-debugging/  spring-boot-app/  spring-security/  tomcat-app/
core-java-9/  deep-jsf/     log4j2-example/  memory-leaks/     README.md  slf4j/             spring-mvc/       thread-pools/     webservices/

3. Using git checkout

To clone a subdirectory or file with git checkoutwe’ll start by cloning the repository without a HEAD checkout:

$ git clone --no-checkout --depth=1 https://github.com/Baeldung/stackify.git

Running the command above will recreate the repository’s .git folder locally. However, the local repo’s root directory will have no files or subdirectories. We can confirm this with tree:

$ tree stackify
stackify

0 directories, 0 files

After doing the –no-checkout clone, we’ll cd into the local repo’s main directory:

$ cd stackify

Then, we’ll check out the subdirectory or file we need using git checkout and the branch name:

$ git checkout master -- tomcat-app

Now, we have only the tomcat-app subdirectory:

$ ls -F
tomcat-app/

Using this method to clone a single subdirectory or file from a Git repository means that the other files and subdirectories would be deleted when we commit changes.

So, we’ll use this method when we’re okay with deleting the repo’s other resources. Alternatively, we could use this to get a file or subdirectory and then unlink it from the repository by deleting the .git directory – basically like downloading the file or subdirectory.

Unlike the git checkout method, git sparse-checkout does not delete the other files and subdirectories when we commit changes. Whatever we do to the tracked resource only affects that resource. So, even when we push to the remote repository, only the tracked file in the remote repository is updated.

4. Using git show

If we already have a local repository and we want to download one of its files, we can redirect the output from git show to a local file:

$ git --git-dir ./stackify/.git show master:README.md > /home/baeldung/stackify-README.md

As with the git checkout method, we’ll only use this when we need the files only (without the repo).

5. Conclusion

In this article, we discussed how to clone only the subdirectory of a repository using git clone and git sparse-checkout. We also talked about how to clone resources from a repository when we do not need said resources linked to the repository.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.