How do I clone a subdirectory only of a Git repository?

I have my Git repository which, at the root, has two sub directories:

/finisht
/static

When this was in SVN, /finisht was checked out in one place, while /static was checked out elsewhere, like so:

svn co svn+ssh://admin@domain.com/home/admin/repos/finisht/static static

Is there a way to do this with Git?


This answer is outdated and only apply to git versions lower than 1.7.0 (Feb. 2012). See below for newer versions.

No, that's not possible in Git.

Implementing something like this in Git would be a substantial effort and it would mean that the integrity of the clientside repository could no longer be guaranteed. If you are interested, search for discussions on "sparse clone" and "sparse fetch" on the git mailinglist.

In general, the consensus in the Git community is that if you have several directories that are always checked out independently, then these are really two different projects and should live in two different repositories. You can glue them back together using Git Submodules.


What you are trying to do is called a sparse checkout , and that feature was added in git 1.7.0 (Feb. 2012). The steps to do a sparse clone are as follows:

mkdir <repo>
cd <repo>
git init
git remote add -f origin <url>

This creates an empty repository with your remote, and fetches all objects but doesn't check them out. Then do:

git config core.sparseCheckout true

Now you need to define which files/folders you want to actually check out. This is done by listing them in .git/info/sparse-checkout , eg:

echo "some/dir/" >> .git/info/sparse-checkout
echo "another/sub/tree" >> .git/info/sparse-checkout

Last but not least, update your empty repo with the state from the remote:

git pull origin master

You will now have files "checked out" for some/dir and another/sub/tree on your file system (with those paths still), and no other paths present.

You might want to have a look at the extended tutorial and you should probably read the official documentation for sparse checkout.

As a function:

function git_sparse_clone() (
  rurl="$1" localdir="$2" && shift 2

  mkdir -p "$localdir"
  cd "$localdir"

  git init
  git remote add -f origin "$rurl"

  git config core.sparseCheckout true

  # Loops over remaining args
  for i; do
    echo "$i" >> .git/info/sparse-checkout
  done

  git pull origin master
)

Usage:

git_sparse_clone "http://github.com/tj/n" "./local/location" "/bin"

Note that this will still download the whole repository from the server – only the checkout is reduced in size. At the moment it is not possible to clone only a single directory. But if you don't need the history of the repository, you can at least save on bandwidth by creating a shallow clone. See udondan's answer below for information on how to combine shallow clone and sparse checkout.


You can combine the sparse checkout and the shallow clone features. The shallow clone cuts off the history and the sparse checkout only pulls the files matching your patterns.

git init <repo>
cd <repo>
git remote add origin <url>
git config core.sparsecheckout true
echo "finisht/*" >> .git/info/sparse-checkout
git pull --depth=1 origin master

You'll need minimum git 1.9 for this to work. Tested it myself only with 2.2.0 and 2.2.2.

This way you'll be still able to push , which is not possible with git archive .

链接地址: http://www.djcxy.com/p/27072.html

上一篇: git克隆时,远端意外挂断

下一篇: 如何克隆仅Git存储库的子目录?