Checkout subdirectories in Git?
Is it possible to check out subdirectories of a repository in Git?
Imagine I am setting up a new WordPress installation. I will create two new directories for my plugin and theme customization:
-
wordpress/wp-content/plugins/myplugins/
wordpress/wp-content/themes/mytheme/
I want to maintain these directories via Git. In Subversion, I would accomplish this by having trunk/myplugins/
and trunk/mytheme/
directories and checking out subdirectories. Does Git have a way to accomplish the same task using a single repository?
I could just be missing the boat on some Git paradigm, as a long time SVN user with little exposure to Git.
Edit: Multiple branches storing different content is an interesting way to handle this.
Sparse checkouts are now in Git 1.7.
Also see the question “Is it possible to do a sparse checkout without checking out the whole repository first?”.
Note that sparse checkouts still require you to download the whole repository, even though some of the files Git downloads won't end up in your working tree.
There is no real way to do that in git. And if you won’t be making changes that affect both trees at once as a single work unit, there is no good reason to use a single repository for both. I thought I would miss this Subversion feature, but I found that creating repositories has so little administrative mental overhead (simply due to the fact that repositories are stored right next to their working copy, rather than requiring me to explicitly pick some place outside of the working copy) that I got used to just making lots of small single-purpose repositories.
If you insist (or really need it), though, you could make a git repository with just mytheme
and myplugins
directories and symlink those from within the WordPress install.
MDCore wrote:
making a commit to, e.g., mytheme will increment the revision number for myplugin
Note that this is not a concern for git, if you do decide to put both directories in a single repository, because git does away entirely with the concept of monotonically increasing revision numbers of any form.
The sole criterion for what things to put together in a single repository in git is whether it constitutes a single unit, ie. in your case whether there are changes where it does not make sense to look at the edits in each directory in isolation. If you have changes where you need to edit files in both directories at once and the edits belong together, they should be one repository. If not, then don’t glom them together.
Git really really wants you to use separate repositories for separate entities.
submodules
Submodules do not address the desire to keep both directories in one repository, because they would actually enforce having a separate repository for each directory, which are then brought together in another repository using submodules. Worse, since the directories inside the WordPress install are not direct subdirectories of the same directory and are also part of a hierarchy with many other files, using the per-directory repositories as submodules in a unified repository would offer no benefit whatsoever, because the unified repository would not reflect any use case/need.
One thing I don't like about sparse checkouts, is that if you want to checkout a subdirectory that is a few directories deep, your directory structure must contain all directories leading to it.
How I work around this is to clone the repo in a place that is not my workspace and then create a symbolic link in my workspace directory to the subdirectory in the repository. Git works like this quite nicely because things like git status will display the change files relative to your current working directory.
git clone --filter
from git 2.19 now works on GitHub (tested 2020-09-18, git 2.25.1)
This option was added together with an update to the remote protocol, and it truly prevents objects from being downloaded from the server.
To clone only objects required for d1
of this repository: https://github.com/cirosantilli/test-git-partial-clone I can do:
git clone \
--depth 1 \
--filter=blob:none \
--no-checkout \
https://github.com/cirosantilli/test-git-partial-clone \
;
cd test-git-partial-clone
git checkout master -- d1
I have covered this in more detail at: Git: How do I clone a subdirectory only of a Git repository?
Actually, "narrow" or "partial" or "sparse" checkouts are under current, heavy development for Git. Note, you'll still have the full repository under .git
. So, the other two posts are current for the current state of Git but it looks like we will be able to do sparse checkouts eventually. Checkout the mailing lists if you're interested in more details -- they're changing rapidly.