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
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
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 and read-tree.
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 )
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.
As of Git 2.25.0 (Jan 2020) an experimental sparse-checkout command is added in Git:
git sparse-checkout init # same as: # git config core.sparseCheckout true git sparse-checkout set "A/B" # same as: # echo "A/B" >> .git/info/sparse-checkout git sparse-checkout list # same as: # cat .git/info/sparse-checkout