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












1093














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?










share|improve this question




















  • 12




    possible duplicate of Checkout subdirectories in Git?
    – Joachim Breitner
    Jul 4 '13 at 8:43






  • 1




    For a 2014's user, what the git clone simplest command?? I used this simple answer. If there are something more simple, please comment
    – Peter Krauss
    Nov 1 '14 at 12:00












  • For those trying to clone the contents of the repository (not creating the root folder), this is a very easy solution: stackoverflow.com/questions/6224626/…
    – Marc
    Mar 29 '15 at 12:38






  • 3




    @OP Can you change the accepted answer to @Chronial's answer?
    – Cole Johnson
    Oct 13 '15 at 23:27










  • @JoachimBreitner: That question is about checking out subdirectories in Git (which is easy), whereas this question is about cloning subdirectories in Git (which is impossible).
    – Jörg W Mittag
    Aug 31 at 14:48
















1093














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?










share|improve this question




















  • 12




    possible duplicate of Checkout subdirectories in Git?
    – Joachim Breitner
    Jul 4 '13 at 8:43






  • 1




    For a 2014's user, what the git clone simplest command?? I used this simple answer. If there are something more simple, please comment
    – Peter Krauss
    Nov 1 '14 at 12:00












  • For those trying to clone the contents of the repository (not creating the root folder), this is a very easy solution: stackoverflow.com/questions/6224626/…
    – Marc
    Mar 29 '15 at 12:38






  • 3




    @OP Can you change the accepted answer to @Chronial's answer?
    – Cole Johnson
    Oct 13 '15 at 23:27










  • @JoachimBreitner: That question is about checking out subdirectories in Git (which is easy), whereas this question is about cloning subdirectories in Git (which is impossible).
    – Jörg W Mittag
    Aug 31 at 14:48














1093












1093








1093


462





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?










share|improve this question















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?







git repository subfolder git-clone






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Sep 2 '16 at 19:21









Peter Mortensen

13.5k1983111




13.5k1983111










asked Mar 1 '09 at 16:46









Nick Sergeant

10.9k113239




10.9k113239








  • 12




    possible duplicate of Checkout subdirectories in Git?
    – Joachim Breitner
    Jul 4 '13 at 8:43






  • 1




    For a 2014's user, what the git clone simplest command?? I used this simple answer. If there are something more simple, please comment
    – Peter Krauss
    Nov 1 '14 at 12:00












  • For those trying to clone the contents of the repository (not creating the root folder), this is a very easy solution: stackoverflow.com/questions/6224626/…
    – Marc
    Mar 29 '15 at 12:38






  • 3




    @OP Can you change the accepted answer to @Chronial's answer?
    – Cole Johnson
    Oct 13 '15 at 23:27










  • @JoachimBreitner: That question is about checking out subdirectories in Git (which is easy), whereas this question is about cloning subdirectories in Git (which is impossible).
    – Jörg W Mittag
    Aug 31 at 14:48














  • 12




    possible duplicate of Checkout subdirectories in Git?
    – Joachim Breitner
    Jul 4 '13 at 8:43






  • 1




    For a 2014's user, what the git clone simplest command?? I used this simple answer. If there are something more simple, please comment
    – Peter Krauss
    Nov 1 '14 at 12:00












  • For those trying to clone the contents of the repository (not creating the root folder), this is a very easy solution: stackoverflow.com/questions/6224626/…
    – Marc
    Mar 29 '15 at 12:38






  • 3




    @OP Can you change the accepted answer to @Chronial's answer?
    – Cole Johnson
    Oct 13 '15 at 23:27










  • @JoachimBreitner: That question is about checking out subdirectories in Git (which is easy), whereas this question is about cloning subdirectories in Git (which is impossible).
    – Jörg W Mittag
    Aug 31 at 14:48








12




12




possible duplicate of Checkout subdirectories in Git?
– Joachim Breitner
Jul 4 '13 at 8:43




possible duplicate of Checkout subdirectories in Git?
– Joachim Breitner
Jul 4 '13 at 8:43




1




1




For a 2014's user, what the git clone simplest command?? I used this simple answer. If there are something more simple, please comment
– Peter Krauss
Nov 1 '14 at 12:00






For a 2014's user, what the git clone simplest command?? I used this simple answer. If there are something more simple, please comment
– Peter Krauss
Nov 1 '14 at 12:00














For those trying to clone the contents of the repository (not creating the root folder), this is a very easy solution: stackoverflow.com/questions/6224626/…
– Marc
Mar 29 '15 at 12:38




For those trying to clone the contents of the repository (not creating the root folder), this is a very easy solution: stackoverflow.com/questions/6224626/…
– Marc
Mar 29 '15 at 12:38




3




3




@OP Can you change the accepted answer to @Chronial's answer?
– Cole Johnson
Oct 13 '15 at 23:27




@OP Can you change the accepted answer to @Chronial's answer?
– Cole Johnson
Oct 13 '15 at 23:27












@JoachimBreitner: That question is about checking out subdirectories in Git (which is easy), whereas this question is about cloning subdirectories in Git (which is impossible).
– Jörg W Mittag
Aug 31 at 14:48




@JoachimBreitner: That question is about checking out subdirectories in Git (which is easy), whereas this question is about cloning subdirectories in Git (which is impossible).
– Jörg W Mittag
Aug 31 at 14:48












11 Answers
11






active

oldest

votes


















441














EDIT: As of Git 2.19, this is finally possible, as can be seen in this answer: https://stackoverflow.com/a/52269934/2988.



Consider upvoting that answer.



Note: in Git 2.19, only client-side support is implemented, server-side support is still missing, so it only works when cloning local repositories. Also note that large Git hosters, e.g. GitHub, don't actually use the Git server, they use their own implementation, so even if support shows up in the Git server, it does not automatically mean that it works on Git hosters. (OTOH, since they don't use the Git server, they could implement it faster in their own implementations before it shows up in Git server.)





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.






share|improve this answer



















  • 6




    Depending on the scenario, you may want to use git subtree instead of git submodule. See alumnit.ca/~apenwarr/log/?m=200904#30
    – C Pirate
    Aug 3 '09 at 17:12






  • 9




    @StijndeWitt: Sparse checkouts happen during git-read-tree, which is long after get-fetch. The question was not about checking out only a subdirectory, it was about cloning only a subdirectory. I don't see how sparse checkouts could possibly do that, since git-read-tree runs after the clone has already completed.
    – Jörg W Mittag
    Mar 6 '14 at 14:53






  • 8




    Rather than this "stub", would you like for me to delete this answer so Chronial's can float to the top? You can't delete it yourself, because it's accepted, but a moderator can. You would keep the reputation you've earned from it, since it's so old. (I came across this because someone flagged it as "link-only". :-)
    – Cody Gray
    Aug 21 '17 at 17:49






  • 1




    @CodyGray: Chronial answer still clones the entire repository, and not only a subdirectory. (The last paragraph even explicitly says so.) Cloning only a subdirectory is not possible in Git. The network protocol doesn't support it, the storage format doesn't support it. Every single answer to this question always clones the whole repository. The question is a simple Yes/No question, and the answer is two characters: No. If at all, my answer is unnecessarily long, not short.
    – Jörg W Mittag
    Aug 31 at 14:45








  • 1




    @JörgWMittag: Ciro Santili's answer seems to contradict you.
    – Dan Dascalescu
    Nov 4 at 0:53



















1409














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.






share|improve this answer



















  • 11




    on Apple the '-f' perimeter does not work. just do git remote add origin <url> without -f
    – Anno2001
    Feb 17 '13 at 10:58








  • 123




    It is an improvement but still needs to download and store a full copy of the remote repository in origin, which one might like to avoid at all if he is interested only in portions of the codebase (or if there is documentation subfolders as in my case)
    – a1an
    Jun 13 '13 at 12:42






  • 52




    Is there a way to clone desired directory contents (not directory itself) right into my repository? For example I want clone contents of https://github.com/Umkus/nginx-boilerplate/tree/master/src right into /etc/nginx
    – mac
    Apr 10 '14 at 5:40






  • 24




    @Chronial, @ErikE: you're both right / wrong :P The git remote add command does not imply a fetch, but git remote add -f, as used here, does! That's what the -f means.
    – ntc2
    May 16 '14 at 0:02






  • 18




    Using this and --depth=1 I cloned Chromium Devtools in 338 MB instead of 4.9 GB of full Blink source + history. Excellent.
    – Rudie
    Oct 22 '14 at 19:26



















351














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.






share|improve this answer



















  • 24




    This is the correct answer. All the other answers pull way too much data.
    – Johan
    Apr 14 '15 at 18:37






  • 17




    This is useful, and may be the best available answer, but it still clones the content that you don't care about (if it is on the branch that you pull), even though it doesn't show up in the checkout.
    – nobar
    Aug 25 '15 at 21:54






  • 2




    doesn't work for me when the last command is not git pull --depth=1 origin master but git pull --depth=1 origin <any-other-branch>. this is so strange, see my question here: stackoverflow.com/questions/35820630/…
    – Shuman
    Mar 6 '16 at 0:15






  • 2




    On Windows, the second-to-last line needs to omit the quotes, or the pull fails.
    – nateirvin
    Mar 31 '16 at 17:01






  • 4




    This still downloads all data! Found this solution, using svn: stackoverflow.com/a/18324458/2302437
    – Ben Marten
    May 18 '16 at 0:09



















98














For other users who just want to download a file/folder from github, simply use:



svn export <repo>/trunk/<folder>


e.g.



svn export https://github.com/lodash/lodash.com/trunk/docs


(yes, that's svn here. apparently in 2016 you still need svn to simply download some github files)



Courtesy: Download a single folder or directory from a GitHub repo



Important - Make sure you update the github URL and replace /tree/master/ with '/trunk/'.



As bash script:



git-download(){
folder=${@/tree/master/trunk}
folder=${folder/blob/master/trunk}
svn export $folder
}


Note
This method downloads a folder, does not clone/checkout it. You can't push changes back to the repository. On the other hand - this results in smaller download compared to sparse checkout or shallow checkout.






share|improve this answer



















  • 7




    only version which worked for me with github. The git commands checked out >10k files, the svn export only the 700 i wanted. Thanks!
    – Christopher Lörken
    Feb 1 '17 at 18:19






  • 3




    Tried doing this with https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity but got svn: E170000: URL 'https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity' doesn't exist error :(
    – zthomas.nc
    Feb 19 '17 at 21:55








  • 6




    @zthomas.nc You need to remove the 'trunk' preceding udacity, and replace /tree/master/ with /trunk/ instead.
    – Speedy
    Mar 22 '17 at 17:01






  • 1




    This command was the one that worked for me! I just wanted to get a copy of a file from a repo so I could modify it locally. Good old SVN to the rescue!
    – Michael J
    Jun 2 '17 at 0:32






  • 2




    it works, but seems slow. takes a bit to start and then the files roll by relatively slowly
    – Aryeh Beitz
    Dec 24 '17 at 10:15



















65














If you never plan to interact with the repository from which you cloned, you can do a full git clone and rewrite your repository using git filter-branch --subdirectory-filter. This way, at least the history will be preserved.






share|improve this answer



















  • 9




    For people that doesn't know the command, it is git filter-branch --subdirectory-filter <subdirectory>
    – Jaime Hablutzel
    Oct 26 '14 at 14:32






  • 9




    This method has the advantage that the subdirectory you choose becomes the root of the new repository, which happens to be exactly what I want.
    – Andrew Schulman
    Dec 23 '14 at 21:27










  • git log --all still shows all logs..
    – cychoi
    Jul 30 '15 at 6:15



















63














Git 1.7.0 has “sparse checkouts”. See
“core.sparseCheckout” in the git config manpage,
“Sparse checkout” in the git read-tree manpage, and
“Skip-worktree bit” in the git update-index manpage.



The interface is not as convenient as SVN’s (e.g. there is no way to make a sparse checkout at the time of an initial clone), but the base functionality upon which simpler interfaces could be built is now available.






share|improve this answer































    60














    This looks far simpler:



    git archive --remote=<repo_url> <branch> <path> | tar xvf -





    share|improve this answer



















    • 17




      When I do this on github I get fatal: Operation not supported by protocol. Unexpected end of command stream
      – Michael Fox
      Sep 25 '14 at 17:37








    • 4




      This works with bitbucket =)
      – Paul Rigor
      Oct 23 '14 at 5:05






    • 2




      If you're using github you can use svn export instead
      – 0sh
      Jul 5 '15 at 15:25






    • 2




      Won't work wiht Github --> Invalid command: 'git-upload-archive 'xxx/yyy.git'' You appear to be using ssh to clone a git:// URL. Make sure your core.gitProxy config option and the GIT_PROXY_COMMAND environment variable are NOT set. fatal: The remote end hung up unexpectedly
      – Nianliang
      Jul 14 '15 at 15:19






    • 2




      The reason why this doesn't work with GitHub: "We don't support using git-archive to pull an archive directly from GitHub. You can either clone the repo locally and run git-archive, or click on the Download ZIP button on the repo page." github.com/xuwupeng2000/capistrano-scm-gitcopy/issues/16
      – Donn Lee
      Aug 29 '16 at 23:17



















    43














    git clone --filter from Git 2.19



    This option will actually skip fetching unneeded objects from the server:



    git clone --depth 1 --no-checkout --filter=blob:none 
    "file://$(pwd)/server_repo" local_repo
    cd local_repo
    git checkout master -- mydir/


    The server should be configured with:



    git config --local uploadpack.allowfilter 1
    git config --local uploadpack.allowanysha1inwant 1


    An extension was made to the Git remote protocol to support this feature in v2.19.0, but there is no server support at that time. But it can already be locally tested.



    TODO: --filter=blob:none skips all blobs, but still fetches all tree objects. But on a normal repo, this should be tiny compared to the files themselves, so this is already good enough. Asked at: https://www.spinics.net/lists/git/msg342006.html Devs replied a --filter=tree:0 is in the works to do that.



    Remember that --depth 1 already implies --single-branch, see also: How do I clone a single branch in Git?



    file://$(path) is required to overcome git clone protocol shenanigans: How to shallow clone a local git repository with a relative path?



    The format of --filter is documented on man git-rev-list.



    Docs on Git tree:




    • https://github.com/git/git/blob/v2.19.0/Documentation/technical/partial-clone.txt

    • https://github.com/git/git/blob/v2.19.0/Documentation/rev-list-options.txt#L720

    • https://github.com/git/git/blob/v2.19.0/t/t5616-partial-clone.sh


    Test it out



    #!/usr/bin/env bash
    set -eu

    list-objects() (
    git rev-list --all --objects
    echo "master commit SHA: $(git log -1 --format="%H")"
    echo "mybranch commit SHA: $(git log -1 --format="%H")"
    git ls-tree master
    git ls-tree mybranch | grep mybranch
    git ls-tree master~ | grep root
    )

    # Reproducibility.
    export GIT_COMMITTER_NAME='a'
    export GIT_COMMITTER_EMAIL='a'
    export GIT_AUTHOR_NAME='a'
    export GIT_AUTHOR_EMAIL='a'
    export GIT_COMMITTER_DATE='2000-01-01T00:00:00+0000'
    export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'

    rm -rf server_repo local_repo
    mkdir server_repo
    cd server_repo

    # Create repo.
    git init --quiet
    git config --local uploadpack.allowfilter 1
    git config --local uploadpack.allowanysha1inwant 1

    # First commit.
    # Directories present in all branches.
    mkdir d1 d2
    printf 'd1/a' > ./d1/a
    printf 'd1/b' > ./d1/b
    printf 'd2/a' > ./d2/a
    printf 'd2/b' > ./d2/b
    # Present only in root.
    mkdir 'root'
    printf 'root' > ./root/root
    git add .
    git commit -m 'root' --quiet

    # Second commit only on master.
    git rm --quiet -r ./root
    mkdir 'master'
    printf 'master' > ./master/master
    git add .
    git commit -m 'master commit' --quiet

    # Second commit only on mybranch.
    git checkout -b mybranch --quiet master~
    git rm --quiet -r ./root
    mkdir 'mybranch'
    printf 'mybranch' > ./mybranch/mybranch
    git add .
    git commit -m 'mybranch commit' --quiet

    echo "# List and identify all objects"
    list-objects
    echo

    # Restore master.
    git checkout --quiet master
    cd ..

    # Clone. Don't checkout for now, only .git/ dir.
    git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repo
    cd local_repo

    # List missing objects from master.
    echo "# Missing objects after --no-checkout"
    git rev-list --all --quiet --objects --missing=print
    echo

    echo "# Git checkout fails without internet"
    mv ../server_repo ../server_repo.off
    ! git checkout master
    echo

    echo "# Git checkout fetches the missing directory from internet"
    mv ../server_repo.off ../server_repo
    git checkout master -- d1/
    echo

    echo "# Missing objects after checking out d1"
    git rev-list --all --quiet --objects --missing=print


    GitHub upstream.



    Output in Git v2.19.0:



    # List and identify all objects
    c6fcdfaf2b1462f809aecdad83a186eeec00f9c1
    fc5e97944480982cfc180a6d6634699921ee63ec
    7251a83be9a03161acde7b71a8fda9be19f47128
    62d67bce3c672fe2b9065f372726a11e57bade7e
    b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
    308150e8fddde043f3dbbb8573abb6af1df96e63 d1/a
    f70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b
    84de03c312dc741d0f2a66df7b2f168d823e122a d2
    0975df9b39e23c15f63db194df7f45c76528bccb d2/a
    41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b
    7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
    8b25206ff90e9432f6f1a8600f87a7bd695a24af master/master
    ef29f15c9a7c5417944cc09711b6a9ee51b01d89
    19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
    1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranch
    c3760bb1a0ece87cdbaf9a563c77a45e30a4e30e
    a0234da53ec608b54813b4271fbf00ba5318b99f root
    93ca1422a8da0a9effc465eccbcb17e23015542d root/root
    master commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
    mybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
    040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
    040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a d2
    040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
    040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
    040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f root

    # Missing objects after --no-checkout
    ?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
    ?8b25206ff90e9432f6f1a8600f87a7bd695a24af
    ?41484c13520fcbb6e7243a26fdb1fc9405c08520
    ?0975df9b39e23c15f63db194df7f45c76528bccb
    ?308150e8fddde043f3dbbb8573abb6af1df96e63

    # Git checkout fails without internet
    fatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repository
    fatal: Could not read from remote repository.

    Please make sure you have the correct access rights
    and the repository exists.

    # Git checkout fetches the missing directory from internet
    remote: Enumerating objects: 1, done.
    remote: Counting objects: 100% (1/1), done.
    remote: Total 1 (delta 0), reused 0 (delta 0)
    Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
    remote: Enumerating objects: 1, done.
    remote: Counting objects: 100% (1/1), done.
    remote: Total 1 (delta 0), reused 0 (delta 0)
    Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.

    # Missing objects after checking out d1
    ?8b25206ff90e9432f6f1a8600f87a7bd695a24af
    ?41484c13520fcbb6e7243a26fdb1fc9405c08520
    ?0975df9b39e23c15f63db194df7f45c76528bccb


    Conclusions: all blobs from outside of d1/ are missing. E.g. 0975df9b39e23c15f63db194df7f45c76528bccb, which is d2/b is not there after checking out d1/a.



    Note that root/root and mybranch/mybranch are also missing, but --depth 1 hides that from the list of missing files. If you remove --depth 1, then they show on the list of missing files.



    I have a dream



    This feature could revolutionize Git.



    Imagine having all the code base of your enterprise in a single repo without ugly third-party tools like repo.



    Imagine storing huge blobs directly in the repo without any ugly third party extensions.



    Imagine if GitHub would allow per file metadata like stars and permissions, so you can store all your personal stuff under a single repo.



    Imagine if submodules were treated exactly like regular directories: just request a tree SHA, and a DNS-like mechanism resolves your request, first looking on your local ~/.git, then first to closer servers (your enterprise's mirror / cache) and ending up on GitHub.






    share|improve this answer























    • I don't think introducing politics into StackOverflow is a good idea.
      – Weekend
      Dec 19 at 3:14










    • Hi @Weekend , see: github.com/cirosantilli/china-dictatorship/blob/… Let's move further discussion to meta or the issues on that repo.
      – Ciro Santilli 新疆改造中心 六四事件 法轮功
      Dec 19 at 8:50



















    27














    It's not possible to clone subdirectory only with Git, but below are few workarounds.



    Filter branch



    You may want to rewrite the repository to look as if trunk/public_html/ had been its project root, and discard all other history (using filter-branch), try on already checkout branch:



    git filter-branch --subdirectory-filter trunk/public_html -- --all


    Notes: The -- that separates filter-branch options from revision options, and the --all to rewrite all branches and tags. All information including original commit times or merge information will be preserved. This command honors .git/info/grafts file and refs in the refs/replace/ namespace, so if you have any grafts or replacement refs defined, running this command will make them permanent.




    Warning! The rewritten history will have different object names for all the objects and will not converge with the original branch. You will not be able to easily push and distribute the rewritten branch on top of the original branch. Please do not use this command if you do not know the full implications, and avoid using it anyway, if a simple single commit would suffice to fix your problem.






    Sparse checkout



    Here are simple steps with sparse checkout approach which will populate the working directory sparsely, so you can tell Git which folder(s) or file(s) in the working directory are worth checking out.





    1. Clone repository as usual (--no-checkout is optional):



      git clone --no-checkout git@foo/bar.git
      cd bar


      You may skip this step, if you've your repository already cloned.



      Hint: For large repos, consider shallow clone (--depth 1) to checkout only latest revision or/and --single-branch only.




    2. Enable sparseCheckout option:



      git config core.sparseCheckout true



    3. Specify folder(s) for sparse checkout (without space at the end):



      echo "trunk/public_html/*"> .git/info/sparse-checkout


      or edit .git/info/sparse-checkout.




    4. Checkout the branch (e.g. master):



      git checkout master



    Now you should have selected folders in your current directory.



    You may consider symbolic links if you've too many levels of directories or filtering branch instead.









    share|improve this answer























    • Would Filter branch still allow you to pull?
      – sam
      Dec 17 '16 at 19:21






    • 2




      @sam: no. filter-branch would rewrite the parent commits so they'd have different SHA1 IDs, and thus your filtered tree would have no commits in common with the remote tree. git pull wouldn't know where to try to merge from.
      – Peter Cordes
      Jun 15 '17 at 4:06





















    10














    I just wrote a script for GitHub.



    Usage:



    python get_git_sub_dir.py path/to/sub/dir <RECURSIVE>





    share|improve this answer



















    • 11




      FYI, that's for GitHub only.
      – Sz.
      May 25 '14 at 14:49






    • 8




      And apparently this is for downloading a directory, not cloning a piece of a repo with all its metadata... right?
      – LarsH
      Oct 15 '15 at 19:18



















    5














    Here's a shell script I wrote for the use case of a single subdirectory sparse checkout



    coSubDir.sh



    localRepo=$1
    remoteRepo=$2
    subDir=$3


    # Create local repository for subdirectory checkout, make it hidden to avoid having to drill down to the subfolder
    mkdir ./.$localRepo
    cd ./.$localRepo
    git init
    git remote add -f origin $remoteRepo
    git config core.sparseCheckout true

    # Add the subdirectory of interest to the sparse checkout.
    echo $subDir >> .git/info/sparse-checkout

    git pull origin master

    # Create convenience symlink to the subdirectory of interest
    cd ..
    ln -s ./.$localRepo$subDir $localRepo





    share|improve this answer

















    • 1




      Nice script, only something which should be fixed is the symlink, should be ln -s ./.$localRepo/$subDir $localRepo instead of ln -s ./.$localRepo$subDir $localRepo
      – valentin_nasta
      Mar 16 at 8:33










    protected by Tunaki May 24 '16 at 22:30



    Thank you for your interest in this question.
    Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



    Would you like to answer one of these unanswered questions instead?














    11 Answers
    11






    active

    oldest

    votes








    11 Answers
    11






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    441














    EDIT: As of Git 2.19, this is finally possible, as can be seen in this answer: https://stackoverflow.com/a/52269934/2988.



    Consider upvoting that answer.



    Note: in Git 2.19, only client-side support is implemented, server-side support is still missing, so it only works when cloning local repositories. Also note that large Git hosters, e.g. GitHub, don't actually use the Git server, they use their own implementation, so even if support shows up in the Git server, it does not automatically mean that it works on Git hosters. (OTOH, since they don't use the Git server, they could implement it faster in their own implementations before it shows up in Git server.)





    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.






    share|improve this answer



















    • 6




      Depending on the scenario, you may want to use git subtree instead of git submodule. See alumnit.ca/~apenwarr/log/?m=200904#30
      – C Pirate
      Aug 3 '09 at 17:12






    • 9




      @StijndeWitt: Sparse checkouts happen during git-read-tree, which is long after get-fetch. The question was not about checking out only a subdirectory, it was about cloning only a subdirectory. I don't see how sparse checkouts could possibly do that, since git-read-tree runs after the clone has already completed.
      – Jörg W Mittag
      Mar 6 '14 at 14:53






    • 8




      Rather than this "stub", would you like for me to delete this answer so Chronial's can float to the top? You can't delete it yourself, because it's accepted, but a moderator can. You would keep the reputation you've earned from it, since it's so old. (I came across this because someone flagged it as "link-only". :-)
      – Cody Gray
      Aug 21 '17 at 17:49






    • 1




      @CodyGray: Chronial answer still clones the entire repository, and not only a subdirectory. (The last paragraph even explicitly says so.) Cloning only a subdirectory is not possible in Git. The network protocol doesn't support it, the storage format doesn't support it. Every single answer to this question always clones the whole repository. The question is a simple Yes/No question, and the answer is two characters: No. If at all, my answer is unnecessarily long, not short.
      – Jörg W Mittag
      Aug 31 at 14:45








    • 1




      @JörgWMittag: Ciro Santili's answer seems to contradict you.
      – Dan Dascalescu
      Nov 4 at 0:53
















    441














    EDIT: As of Git 2.19, this is finally possible, as can be seen in this answer: https://stackoverflow.com/a/52269934/2988.



    Consider upvoting that answer.



    Note: in Git 2.19, only client-side support is implemented, server-side support is still missing, so it only works when cloning local repositories. Also note that large Git hosters, e.g. GitHub, don't actually use the Git server, they use their own implementation, so even if support shows up in the Git server, it does not automatically mean that it works on Git hosters. (OTOH, since they don't use the Git server, they could implement it faster in their own implementations before it shows up in Git server.)





    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.






    share|improve this answer



















    • 6




      Depending on the scenario, you may want to use git subtree instead of git submodule. See alumnit.ca/~apenwarr/log/?m=200904#30
      – C Pirate
      Aug 3 '09 at 17:12






    • 9




      @StijndeWitt: Sparse checkouts happen during git-read-tree, which is long after get-fetch. The question was not about checking out only a subdirectory, it was about cloning only a subdirectory. I don't see how sparse checkouts could possibly do that, since git-read-tree runs after the clone has already completed.
      – Jörg W Mittag
      Mar 6 '14 at 14:53






    • 8




      Rather than this "stub", would you like for me to delete this answer so Chronial's can float to the top? You can't delete it yourself, because it's accepted, but a moderator can. You would keep the reputation you've earned from it, since it's so old. (I came across this because someone flagged it as "link-only". :-)
      – Cody Gray
      Aug 21 '17 at 17:49






    • 1




      @CodyGray: Chronial answer still clones the entire repository, and not only a subdirectory. (The last paragraph even explicitly says so.) Cloning only a subdirectory is not possible in Git. The network protocol doesn't support it, the storage format doesn't support it. Every single answer to this question always clones the whole repository. The question is a simple Yes/No question, and the answer is two characters: No. If at all, my answer is unnecessarily long, not short.
      – Jörg W Mittag
      Aug 31 at 14:45








    • 1




      @JörgWMittag: Ciro Santili's answer seems to contradict you.
      – Dan Dascalescu
      Nov 4 at 0:53














    441












    441








    441






    EDIT: As of Git 2.19, this is finally possible, as can be seen in this answer: https://stackoverflow.com/a/52269934/2988.



    Consider upvoting that answer.



    Note: in Git 2.19, only client-side support is implemented, server-side support is still missing, so it only works when cloning local repositories. Also note that large Git hosters, e.g. GitHub, don't actually use the Git server, they use their own implementation, so even if support shows up in the Git server, it does not automatically mean that it works on Git hosters. (OTOH, since they don't use the Git server, they could implement it faster in their own implementations before it shows up in Git server.)





    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.






    share|improve this answer














    EDIT: As of Git 2.19, this is finally possible, as can be seen in this answer: https://stackoverflow.com/a/52269934/2988.



    Consider upvoting that answer.



    Note: in Git 2.19, only client-side support is implemented, server-side support is still missing, so it only works when cloning local repositories. Also note that large Git hosters, e.g. GitHub, don't actually use the Git server, they use their own implementation, so even if support shows up in the Git server, it does not automatically mean that it works on Git hosters. (OTOH, since they don't use the Git server, they could implement it faster in their own implementations before it shows up in Git server.)





    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.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 12 at 16:35









    getThingsDone

    6212




    6212










    answered Mar 1 '09 at 18:00









    Jörg W Mittag

    288k62355547




    288k62355547








    • 6




      Depending on the scenario, you may want to use git subtree instead of git submodule. See alumnit.ca/~apenwarr/log/?m=200904#30
      – C Pirate
      Aug 3 '09 at 17:12






    • 9




      @StijndeWitt: Sparse checkouts happen during git-read-tree, which is long after get-fetch. The question was not about checking out only a subdirectory, it was about cloning only a subdirectory. I don't see how sparse checkouts could possibly do that, since git-read-tree runs after the clone has already completed.
      – Jörg W Mittag
      Mar 6 '14 at 14:53






    • 8




      Rather than this "stub", would you like for me to delete this answer so Chronial's can float to the top? You can't delete it yourself, because it's accepted, but a moderator can. You would keep the reputation you've earned from it, since it's so old. (I came across this because someone flagged it as "link-only". :-)
      – Cody Gray
      Aug 21 '17 at 17:49






    • 1




      @CodyGray: Chronial answer still clones the entire repository, and not only a subdirectory. (The last paragraph even explicitly says so.) Cloning only a subdirectory is not possible in Git. The network protocol doesn't support it, the storage format doesn't support it. Every single answer to this question always clones the whole repository. The question is a simple Yes/No question, and the answer is two characters: No. If at all, my answer is unnecessarily long, not short.
      – Jörg W Mittag
      Aug 31 at 14:45








    • 1




      @JörgWMittag: Ciro Santili's answer seems to contradict you.
      – Dan Dascalescu
      Nov 4 at 0:53














    • 6




      Depending on the scenario, you may want to use git subtree instead of git submodule. See alumnit.ca/~apenwarr/log/?m=200904#30
      – C Pirate
      Aug 3 '09 at 17:12






    • 9




      @StijndeWitt: Sparse checkouts happen during git-read-tree, which is long after get-fetch. The question was not about checking out only a subdirectory, it was about cloning only a subdirectory. I don't see how sparse checkouts could possibly do that, since git-read-tree runs after the clone has already completed.
      – Jörg W Mittag
      Mar 6 '14 at 14:53






    • 8




      Rather than this "stub", would you like for me to delete this answer so Chronial's can float to the top? You can't delete it yourself, because it's accepted, but a moderator can. You would keep the reputation you've earned from it, since it's so old. (I came across this because someone flagged it as "link-only". :-)
      – Cody Gray
      Aug 21 '17 at 17:49






    • 1




      @CodyGray: Chronial answer still clones the entire repository, and not only a subdirectory. (The last paragraph even explicitly says so.) Cloning only a subdirectory is not possible in Git. The network protocol doesn't support it, the storage format doesn't support it. Every single answer to this question always clones the whole repository. The question is a simple Yes/No question, and the answer is two characters: No. If at all, my answer is unnecessarily long, not short.
      – Jörg W Mittag
      Aug 31 at 14:45








    • 1




      @JörgWMittag: Ciro Santili's answer seems to contradict you.
      – Dan Dascalescu
      Nov 4 at 0:53








    6




    6




    Depending on the scenario, you may want to use git subtree instead of git submodule. See alumnit.ca/~apenwarr/log/?m=200904#30
    – C Pirate
    Aug 3 '09 at 17:12




    Depending on the scenario, you may want to use git subtree instead of git submodule. See alumnit.ca/~apenwarr/log/?m=200904#30
    – C Pirate
    Aug 3 '09 at 17:12




    9




    9




    @StijndeWitt: Sparse checkouts happen during git-read-tree, which is long after get-fetch. The question was not about checking out only a subdirectory, it was about cloning only a subdirectory. I don't see how sparse checkouts could possibly do that, since git-read-tree runs after the clone has already completed.
    – Jörg W Mittag
    Mar 6 '14 at 14:53




    @StijndeWitt: Sparse checkouts happen during git-read-tree, which is long after get-fetch. The question was not about checking out only a subdirectory, it was about cloning only a subdirectory. I don't see how sparse checkouts could possibly do that, since git-read-tree runs after the clone has already completed.
    – Jörg W Mittag
    Mar 6 '14 at 14:53




    8




    8




    Rather than this "stub", would you like for me to delete this answer so Chronial's can float to the top? You can't delete it yourself, because it's accepted, but a moderator can. You would keep the reputation you've earned from it, since it's so old. (I came across this because someone flagged it as "link-only". :-)
    – Cody Gray
    Aug 21 '17 at 17:49




    Rather than this "stub", would you like for me to delete this answer so Chronial's can float to the top? You can't delete it yourself, because it's accepted, but a moderator can. You would keep the reputation you've earned from it, since it's so old. (I came across this because someone flagged it as "link-only". :-)
    – Cody Gray
    Aug 21 '17 at 17:49




    1




    1




    @CodyGray: Chronial answer still clones the entire repository, and not only a subdirectory. (The last paragraph even explicitly says so.) Cloning only a subdirectory is not possible in Git. The network protocol doesn't support it, the storage format doesn't support it. Every single answer to this question always clones the whole repository. The question is a simple Yes/No question, and the answer is two characters: No. If at all, my answer is unnecessarily long, not short.
    – Jörg W Mittag
    Aug 31 at 14:45






    @CodyGray: Chronial answer still clones the entire repository, and not only a subdirectory. (The last paragraph even explicitly says so.) Cloning only a subdirectory is not possible in Git. The network protocol doesn't support it, the storage format doesn't support it. Every single answer to this question always clones the whole repository. The question is a simple Yes/No question, and the answer is two characters: No. If at all, my answer is unnecessarily long, not short.
    – Jörg W Mittag
    Aug 31 at 14:45






    1




    1




    @JörgWMittag: Ciro Santili's answer seems to contradict you.
    – Dan Dascalescu
    Nov 4 at 0:53




    @JörgWMittag: Ciro Santili's answer seems to contradict you.
    – Dan Dascalescu
    Nov 4 at 0:53













    1409














    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.






    share|improve this answer



















    • 11




      on Apple the '-f' perimeter does not work. just do git remote add origin <url> without -f
      – Anno2001
      Feb 17 '13 at 10:58








    • 123




      It is an improvement but still needs to download and store a full copy of the remote repository in origin, which one might like to avoid at all if he is interested only in portions of the codebase (or if there is documentation subfolders as in my case)
      – a1an
      Jun 13 '13 at 12:42






    • 52




      Is there a way to clone desired directory contents (not directory itself) right into my repository? For example I want clone contents of https://github.com/Umkus/nginx-boilerplate/tree/master/src right into /etc/nginx
      – mac
      Apr 10 '14 at 5:40






    • 24




      @Chronial, @ErikE: you're both right / wrong :P The git remote add command does not imply a fetch, but git remote add -f, as used here, does! That's what the -f means.
      – ntc2
      May 16 '14 at 0:02






    • 18




      Using this and --depth=1 I cloned Chromium Devtools in 338 MB instead of 4.9 GB of full Blink source + history. Excellent.
      – Rudie
      Oct 22 '14 at 19:26
















    1409














    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.






    share|improve this answer



















    • 11




      on Apple the '-f' perimeter does not work. just do git remote add origin <url> without -f
      – Anno2001
      Feb 17 '13 at 10:58








    • 123




      It is an improvement but still needs to download and store a full copy of the remote repository in origin, which one might like to avoid at all if he is interested only in portions of the codebase (or if there is documentation subfolders as in my case)
      – a1an
      Jun 13 '13 at 12:42






    • 52




      Is there a way to clone desired directory contents (not directory itself) right into my repository? For example I want clone contents of https://github.com/Umkus/nginx-boilerplate/tree/master/src right into /etc/nginx
      – mac
      Apr 10 '14 at 5:40






    • 24




      @Chronial, @ErikE: you're both right / wrong :P The git remote add command does not imply a fetch, but git remote add -f, as used here, does! That's what the -f means.
      – ntc2
      May 16 '14 at 0:02






    • 18




      Using this and --depth=1 I cloned Chromium Devtools in 338 MB instead of 4.9 GB of full Blink source + history. Excellent.
      – Rudie
      Oct 22 '14 at 19:26














    1409












    1409








    1409






    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.






    share|improve this answer














    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.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Apr 3 at 14:05









    Nick Bull

    6,38931425




    6,38931425










    answered Dec 6 '12 at 7:37









    Chronial

    43.2k115768




    43.2k115768








    • 11




      on Apple the '-f' perimeter does not work. just do git remote add origin <url> without -f
      – Anno2001
      Feb 17 '13 at 10:58








    • 123




      It is an improvement but still needs to download and store a full copy of the remote repository in origin, which one might like to avoid at all if he is interested only in portions of the codebase (or if there is documentation subfolders as in my case)
      – a1an
      Jun 13 '13 at 12:42






    • 52




      Is there a way to clone desired directory contents (not directory itself) right into my repository? For example I want clone contents of https://github.com/Umkus/nginx-boilerplate/tree/master/src right into /etc/nginx
      – mac
      Apr 10 '14 at 5:40






    • 24




      @Chronial, @ErikE: you're both right / wrong :P The git remote add command does not imply a fetch, but git remote add -f, as used here, does! That's what the -f means.
      – ntc2
      May 16 '14 at 0:02






    • 18




      Using this and --depth=1 I cloned Chromium Devtools in 338 MB instead of 4.9 GB of full Blink source + history. Excellent.
      – Rudie
      Oct 22 '14 at 19:26














    • 11




      on Apple the '-f' perimeter does not work. just do git remote add origin <url> without -f
      – Anno2001
      Feb 17 '13 at 10:58








    • 123




      It is an improvement but still needs to download and store a full copy of the remote repository in origin, which one might like to avoid at all if he is interested only in portions of the codebase (or if there is documentation subfolders as in my case)
      – a1an
      Jun 13 '13 at 12:42






    • 52




      Is there a way to clone desired directory contents (not directory itself) right into my repository? For example I want clone contents of https://github.com/Umkus/nginx-boilerplate/tree/master/src right into /etc/nginx
      – mac
      Apr 10 '14 at 5:40






    • 24




      @Chronial, @ErikE: you're both right / wrong :P The git remote add command does not imply a fetch, but git remote add -f, as used here, does! That's what the -f means.
      – ntc2
      May 16 '14 at 0:02






    • 18




      Using this and --depth=1 I cloned Chromium Devtools in 338 MB instead of 4.9 GB of full Blink source + history. Excellent.
      – Rudie
      Oct 22 '14 at 19:26








    11




    11




    on Apple the '-f' perimeter does not work. just do git remote add origin <url> without -f
    – Anno2001
    Feb 17 '13 at 10:58






    on Apple the '-f' perimeter does not work. just do git remote add origin <url> without -f
    – Anno2001
    Feb 17 '13 at 10:58






    123




    123




    It is an improvement but still needs to download and store a full copy of the remote repository in origin, which one might like to avoid at all if he is interested only in portions of the codebase (or if there is documentation subfolders as in my case)
    – a1an
    Jun 13 '13 at 12:42




    It is an improvement but still needs to download and store a full copy of the remote repository in origin, which one might like to avoid at all if he is interested only in portions of the codebase (or if there is documentation subfolders as in my case)
    – a1an
    Jun 13 '13 at 12:42




    52




    52




    Is there a way to clone desired directory contents (not directory itself) right into my repository? For example I want clone contents of https://github.com/Umkus/nginx-boilerplate/tree/master/src right into /etc/nginx
    – mac
    Apr 10 '14 at 5:40




    Is there a way to clone desired directory contents (not directory itself) right into my repository? For example I want clone contents of https://github.com/Umkus/nginx-boilerplate/tree/master/src right into /etc/nginx
    – mac
    Apr 10 '14 at 5:40




    24




    24




    @Chronial, @ErikE: you're both right / wrong :P The git remote add command does not imply a fetch, but git remote add -f, as used here, does! That's what the -f means.
    – ntc2
    May 16 '14 at 0:02




    @Chronial, @ErikE: you're both right / wrong :P The git remote add command does not imply a fetch, but git remote add -f, as used here, does! That's what the -f means.
    – ntc2
    May 16 '14 at 0:02




    18




    18




    Using this and --depth=1 I cloned Chromium Devtools in 338 MB instead of 4.9 GB of full Blink source + history. Excellent.
    – Rudie
    Oct 22 '14 at 19:26




    Using this and --depth=1 I cloned Chromium Devtools in 338 MB instead of 4.9 GB of full Blink source + history. Excellent.
    – Rudie
    Oct 22 '14 at 19:26











    351














    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.






    share|improve this answer



















    • 24




      This is the correct answer. All the other answers pull way too much data.
      – Johan
      Apr 14 '15 at 18:37






    • 17




      This is useful, and may be the best available answer, but it still clones the content that you don't care about (if it is on the branch that you pull), even though it doesn't show up in the checkout.
      – nobar
      Aug 25 '15 at 21:54






    • 2




      doesn't work for me when the last command is not git pull --depth=1 origin master but git pull --depth=1 origin <any-other-branch>. this is so strange, see my question here: stackoverflow.com/questions/35820630/…
      – Shuman
      Mar 6 '16 at 0:15






    • 2




      On Windows, the second-to-last line needs to omit the quotes, or the pull fails.
      – nateirvin
      Mar 31 '16 at 17:01






    • 4




      This still downloads all data! Found this solution, using svn: stackoverflow.com/a/18324458/2302437
      – Ben Marten
      May 18 '16 at 0:09
















    351














    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.






    share|improve this answer



















    • 24




      This is the correct answer. All the other answers pull way too much data.
      – Johan
      Apr 14 '15 at 18:37






    • 17




      This is useful, and may be the best available answer, but it still clones the content that you don't care about (if it is on the branch that you pull), even though it doesn't show up in the checkout.
      – nobar
      Aug 25 '15 at 21:54






    • 2




      doesn't work for me when the last command is not git pull --depth=1 origin master but git pull --depth=1 origin <any-other-branch>. this is so strange, see my question here: stackoverflow.com/questions/35820630/…
      – Shuman
      Mar 6 '16 at 0:15






    • 2




      On Windows, the second-to-last line needs to omit the quotes, or the pull fails.
      – nateirvin
      Mar 31 '16 at 17:01






    • 4




      This still downloads all data! Found this solution, using svn: stackoverflow.com/a/18324458/2302437
      – Ben Marten
      May 18 '16 at 0:09














    351












    351








    351






    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.






    share|improve this answer














    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.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Feb 25 '15 at 0:22

























    answered Jan 20 '15 at 7:33









    udondan

    33.2k9110124




    33.2k9110124








    • 24




      This is the correct answer. All the other answers pull way too much data.
      – Johan
      Apr 14 '15 at 18:37






    • 17




      This is useful, and may be the best available answer, but it still clones the content that you don't care about (if it is on the branch that you pull), even though it doesn't show up in the checkout.
      – nobar
      Aug 25 '15 at 21:54






    • 2




      doesn't work for me when the last command is not git pull --depth=1 origin master but git pull --depth=1 origin <any-other-branch>. this is so strange, see my question here: stackoverflow.com/questions/35820630/…
      – Shuman
      Mar 6 '16 at 0:15






    • 2




      On Windows, the second-to-last line needs to omit the quotes, or the pull fails.
      – nateirvin
      Mar 31 '16 at 17:01






    • 4




      This still downloads all data! Found this solution, using svn: stackoverflow.com/a/18324458/2302437
      – Ben Marten
      May 18 '16 at 0:09














    • 24




      This is the correct answer. All the other answers pull way too much data.
      – Johan
      Apr 14 '15 at 18:37






    • 17




      This is useful, and may be the best available answer, but it still clones the content that you don't care about (if it is on the branch that you pull), even though it doesn't show up in the checkout.
      – nobar
      Aug 25 '15 at 21:54






    • 2




      doesn't work for me when the last command is not git pull --depth=1 origin master but git pull --depth=1 origin <any-other-branch>. this is so strange, see my question here: stackoverflow.com/questions/35820630/…
      – Shuman
      Mar 6 '16 at 0:15






    • 2




      On Windows, the second-to-last line needs to omit the quotes, or the pull fails.
      – nateirvin
      Mar 31 '16 at 17:01






    • 4




      This still downloads all data! Found this solution, using svn: stackoverflow.com/a/18324458/2302437
      – Ben Marten
      May 18 '16 at 0:09








    24




    24




    This is the correct answer. All the other answers pull way too much data.
    – Johan
    Apr 14 '15 at 18:37




    This is the correct answer. All the other answers pull way too much data.
    – Johan
    Apr 14 '15 at 18:37




    17




    17




    This is useful, and may be the best available answer, but it still clones the content that you don't care about (if it is on the branch that you pull), even though it doesn't show up in the checkout.
    – nobar
    Aug 25 '15 at 21:54




    This is useful, and may be the best available answer, but it still clones the content that you don't care about (if it is on the branch that you pull), even though it doesn't show up in the checkout.
    – nobar
    Aug 25 '15 at 21:54




    2




    2




    doesn't work for me when the last command is not git pull --depth=1 origin master but git pull --depth=1 origin <any-other-branch>. this is so strange, see my question here: stackoverflow.com/questions/35820630/…
    – Shuman
    Mar 6 '16 at 0:15




    doesn't work for me when the last command is not git pull --depth=1 origin master but git pull --depth=1 origin <any-other-branch>. this is so strange, see my question here: stackoverflow.com/questions/35820630/…
    – Shuman
    Mar 6 '16 at 0:15




    2




    2




    On Windows, the second-to-last line needs to omit the quotes, or the pull fails.
    – nateirvin
    Mar 31 '16 at 17:01




    On Windows, the second-to-last line needs to omit the quotes, or the pull fails.
    – nateirvin
    Mar 31 '16 at 17:01




    4




    4




    This still downloads all data! Found this solution, using svn: stackoverflow.com/a/18324458/2302437
    – Ben Marten
    May 18 '16 at 0:09




    This still downloads all data! Found this solution, using svn: stackoverflow.com/a/18324458/2302437
    – Ben Marten
    May 18 '16 at 0:09











    98














    For other users who just want to download a file/folder from github, simply use:



    svn export <repo>/trunk/<folder>


    e.g.



    svn export https://github.com/lodash/lodash.com/trunk/docs


    (yes, that's svn here. apparently in 2016 you still need svn to simply download some github files)



    Courtesy: Download a single folder or directory from a GitHub repo



    Important - Make sure you update the github URL and replace /tree/master/ with '/trunk/'.



    As bash script:



    git-download(){
    folder=${@/tree/master/trunk}
    folder=${folder/blob/master/trunk}
    svn export $folder
    }


    Note
    This method downloads a folder, does not clone/checkout it. You can't push changes back to the repository. On the other hand - this results in smaller download compared to sparse checkout or shallow checkout.






    share|improve this answer



















    • 7




      only version which worked for me with github. The git commands checked out >10k files, the svn export only the 700 i wanted. Thanks!
      – Christopher Lörken
      Feb 1 '17 at 18:19






    • 3




      Tried doing this with https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity but got svn: E170000: URL 'https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity' doesn't exist error :(
      – zthomas.nc
      Feb 19 '17 at 21:55








    • 6




      @zthomas.nc You need to remove the 'trunk' preceding udacity, and replace /tree/master/ with /trunk/ instead.
      – Speedy
      Mar 22 '17 at 17:01






    • 1




      This command was the one that worked for me! I just wanted to get a copy of a file from a repo so I could modify it locally. Good old SVN to the rescue!
      – Michael J
      Jun 2 '17 at 0:32






    • 2




      it works, but seems slow. takes a bit to start and then the files roll by relatively slowly
      – Aryeh Beitz
      Dec 24 '17 at 10:15
















    98














    For other users who just want to download a file/folder from github, simply use:



    svn export <repo>/trunk/<folder>


    e.g.



    svn export https://github.com/lodash/lodash.com/trunk/docs


    (yes, that's svn here. apparently in 2016 you still need svn to simply download some github files)



    Courtesy: Download a single folder or directory from a GitHub repo



    Important - Make sure you update the github URL and replace /tree/master/ with '/trunk/'.



    As bash script:



    git-download(){
    folder=${@/tree/master/trunk}
    folder=${folder/blob/master/trunk}
    svn export $folder
    }


    Note
    This method downloads a folder, does not clone/checkout it. You can't push changes back to the repository. On the other hand - this results in smaller download compared to sparse checkout or shallow checkout.






    share|improve this answer



















    • 7




      only version which worked for me with github. The git commands checked out >10k files, the svn export only the 700 i wanted. Thanks!
      – Christopher Lörken
      Feb 1 '17 at 18:19






    • 3




      Tried doing this with https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity but got svn: E170000: URL 'https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity' doesn't exist error :(
      – zthomas.nc
      Feb 19 '17 at 21:55








    • 6




      @zthomas.nc You need to remove the 'trunk' preceding udacity, and replace /tree/master/ with /trunk/ instead.
      – Speedy
      Mar 22 '17 at 17:01






    • 1




      This command was the one that worked for me! I just wanted to get a copy of a file from a repo so I could modify it locally. Good old SVN to the rescue!
      – Michael J
      Jun 2 '17 at 0:32






    • 2




      it works, but seems slow. takes a bit to start and then the files roll by relatively slowly
      – Aryeh Beitz
      Dec 24 '17 at 10:15














    98












    98








    98






    For other users who just want to download a file/folder from github, simply use:



    svn export <repo>/trunk/<folder>


    e.g.



    svn export https://github.com/lodash/lodash.com/trunk/docs


    (yes, that's svn here. apparently in 2016 you still need svn to simply download some github files)



    Courtesy: Download a single folder or directory from a GitHub repo



    Important - Make sure you update the github URL and replace /tree/master/ with '/trunk/'.



    As bash script:



    git-download(){
    folder=${@/tree/master/trunk}
    folder=${folder/blob/master/trunk}
    svn export $folder
    }


    Note
    This method downloads a folder, does not clone/checkout it. You can't push changes back to the repository. On the other hand - this results in smaller download compared to sparse checkout or shallow checkout.






    share|improve this answer














    For other users who just want to download a file/folder from github, simply use:



    svn export <repo>/trunk/<folder>


    e.g.



    svn export https://github.com/lodash/lodash.com/trunk/docs


    (yes, that's svn here. apparently in 2016 you still need svn to simply download some github files)



    Courtesy: Download a single folder or directory from a GitHub repo



    Important - Make sure you update the github URL and replace /tree/master/ with '/trunk/'.



    As bash script:



    git-download(){
    folder=${@/tree/master/trunk}
    folder=${folder/blob/master/trunk}
    svn export $folder
    }


    Note
    This method downloads a folder, does not clone/checkout it. You can't push changes back to the repository. On the other hand - this results in smaller download compared to sparse checkout or shallow checkout.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jun 18 at 11:32









    Amit G

    1,32521741




    1,32521741










    answered Sep 4 '16 at 13:02









    Anona112

    1,75911228




    1,75911228








    • 7




      only version which worked for me with github. The git commands checked out >10k files, the svn export only the 700 i wanted. Thanks!
      – Christopher Lörken
      Feb 1 '17 at 18:19






    • 3




      Tried doing this with https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity but got svn: E170000: URL 'https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity' doesn't exist error :(
      – zthomas.nc
      Feb 19 '17 at 21:55








    • 6




      @zthomas.nc You need to remove the 'trunk' preceding udacity, and replace /tree/master/ with /trunk/ instead.
      – Speedy
      Mar 22 '17 at 17:01






    • 1




      This command was the one that worked for me! I just wanted to get a copy of a file from a repo so I could modify it locally. Good old SVN to the rescue!
      – Michael J
      Jun 2 '17 at 0:32






    • 2




      it works, but seems slow. takes a bit to start and then the files roll by relatively slowly
      – Aryeh Beitz
      Dec 24 '17 at 10:15














    • 7




      only version which worked for me with github. The git commands checked out >10k files, the svn export only the 700 i wanted. Thanks!
      – Christopher Lörken
      Feb 1 '17 at 18:19






    • 3




      Tried doing this with https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity but got svn: E170000: URL 'https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity' doesn't exist error :(
      – zthomas.nc
      Feb 19 '17 at 21:55








    • 6




      @zthomas.nc You need to remove the 'trunk' preceding udacity, and replace /tree/master/ with /trunk/ instead.
      – Speedy
      Mar 22 '17 at 17:01






    • 1




      This command was the one that worked for me! I just wanted to get a copy of a file from a repo so I could modify it locally. Good old SVN to the rescue!
      – Michael J
      Jun 2 '17 at 0:32






    • 2




      it works, but seems slow. takes a bit to start and then the files roll by relatively slowly
      – Aryeh Beitz
      Dec 24 '17 at 10:15








    7




    7




    only version which worked for me with github. The git commands checked out >10k files, the svn export only the 700 i wanted. Thanks!
    – Christopher Lörken
    Feb 1 '17 at 18:19




    only version which worked for me with github. The git commands checked out >10k files, the svn export only the 700 i wanted. Thanks!
    – Christopher Lörken
    Feb 1 '17 at 18:19




    3




    3




    Tried doing this with https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity but got svn: E170000: URL 'https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity' doesn't exist error :(
    – zthomas.nc
    Feb 19 '17 at 21:55






    Tried doing this with https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity but got svn: E170000: URL 'https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity' doesn't exist error :(
    – zthomas.nc
    Feb 19 '17 at 21:55






    6




    6




    @zthomas.nc You need to remove the 'trunk' preceding udacity, and replace /tree/master/ with /trunk/ instead.
    – Speedy
    Mar 22 '17 at 17:01




    @zthomas.nc You need to remove the 'trunk' preceding udacity, and replace /tree/master/ with /trunk/ instead.
    – Speedy
    Mar 22 '17 at 17:01




    1




    1




    This command was the one that worked for me! I just wanted to get a copy of a file from a repo so I could modify it locally. Good old SVN to the rescue!
    – Michael J
    Jun 2 '17 at 0:32




    This command was the one that worked for me! I just wanted to get a copy of a file from a repo so I could modify it locally. Good old SVN to the rescue!
    – Michael J
    Jun 2 '17 at 0:32




    2




    2




    it works, but seems slow. takes a bit to start and then the files roll by relatively slowly
    – Aryeh Beitz
    Dec 24 '17 at 10:15




    it works, but seems slow. takes a bit to start and then the files roll by relatively slowly
    – Aryeh Beitz
    Dec 24 '17 at 10:15











    65














    If you never plan to interact with the repository from which you cloned, you can do a full git clone and rewrite your repository using git filter-branch --subdirectory-filter. This way, at least the history will be preserved.






    share|improve this answer



















    • 9




      For people that doesn't know the command, it is git filter-branch --subdirectory-filter <subdirectory>
      – Jaime Hablutzel
      Oct 26 '14 at 14:32






    • 9




      This method has the advantage that the subdirectory you choose becomes the root of the new repository, which happens to be exactly what I want.
      – Andrew Schulman
      Dec 23 '14 at 21:27










    • git log --all still shows all logs..
      – cychoi
      Jul 30 '15 at 6:15
















    65














    If you never plan to interact with the repository from which you cloned, you can do a full git clone and rewrite your repository using git filter-branch --subdirectory-filter. This way, at least the history will be preserved.






    share|improve this answer



















    • 9




      For people that doesn't know the command, it is git filter-branch --subdirectory-filter <subdirectory>
      – Jaime Hablutzel
      Oct 26 '14 at 14:32






    • 9




      This method has the advantage that the subdirectory you choose becomes the root of the new repository, which happens to be exactly what I want.
      – Andrew Schulman
      Dec 23 '14 at 21:27










    • git log --all still shows all logs..
      – cychoi
      Jul 30 '15 at 6:15














    65












    65








    65






    If you never plan to interact with the repository from which you cloned, you can do a full git clone and rewrite your repository using git filter-branch --subdirectory-filter. This way, at least the history will be preserved.






    share|improve this answer














    If you never plan to interact with the repository from which you cloned, you can do a full git clone and rewrite your repository using git filter-branch --subdirectory-filter. This way, at least the history will be preserved.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jun 14 '15 at 9:09









    udondan

    33.2k9110124




    33.2k9110124










    answered Mar 1 '09 at 21:17









    hillu

    6,03741926




    6,03741926








    • 9




      For people that doesn't know the command, it is git filter-branch --subdirectory-filter <subdirectory>
      – Jaime Hablutzel
      Oct 26 '14 at 14:32






    • 9




      This method has the advantage that the subdirectory you choose becomes the root of the new repository, which happens to be exactly what I want.
      – Andrew Schulman
      Dec 23 '14 at 21:27










    • git log --all still shows all logs..
      – cychoi
      Jul 30 '15 at 6:15














    • 9




      For people that doesn't know the command, it is git filter-branch --subdirectory-filter <subdirectory>
      – Jaime Hablutzel
      Oct 26 '14 at 14:32






    • 9




      This method has the advantage that the subdirectory you choose becomes the root of the new repository, which happens to be exactly what I want.
      – Andrew Schulman
      Dec 23 '14 at 21:27










    • git log --all still shows all logs..
      – cychoi
      Jul 30 '15 at 6:15








    9




    9




    For people that doesn't know the command, it is git filter-branch --subdirectory-filter <subdirectory>
    – Jaime Hablutzel
    Oct 26 '14 at 14:32




    For people that doesn't know the command, it is git filter-branch --subdirectory-filter <subdirectory>
    – Jaime Hablutzel
    Oct 26 '14 at 14:32




    9




    9




    This method has the advantage that the subdirectory you choose becomes the root of the new repository, which happens to be exactly what I want.
    – Andrew Schulman
    Dec 23 '14 at 21:27




    This method has the advantage that the subdirectory you choose becomes the root of the new repository, which happens to be exactly what I want.
    – Andrew Schulman
    Dec 23 '14 at 21:27












    git log --all still shows all logs..
    – cychoi
    Jul 30 '15 at 6:15




    git log --all still shows all logs..
    – cychoi
    Jul 30 '15 at 6:15











    63














    Git 1.7.0 has “sparse checkouts”. See
    “core.sparseCheckout” in the git config manpage,
    “Sparse checkout” in the git read-tree manpage, and
    “Skip-worktree bit” in the git update-index manpage.



    The interface is not as convenient as SVN’s (e.g. there is no way to make a sparse checkout at the time of an initial clone), but the base functionality upon which simpler interfaces could be built is now available.






    share|improve this answer




























      63














      Git 1.7.0 has “sparse checkouts”. See
      “core.sparseCheckout” in the git config manpage,
      “Sparse checkout” in the git read-tree manpage, and
      “Skip-worktree bit” in the git update-index manpage.



      The interface is not as convenient as SVN’s (e.g. there is no way to make a sparse checkout at the time of an initial clone), but the base functionality upon which simpler interfaces could be built is now available.






      share|improve this answer


























        63












        63








        63






        Git 1.7.0 has “sparse checkouts”. See
        “core.sparseCheckout” in the git config manpage,
        “Sparse checkout” in the git read-tree manpage, and
        “Skip-worktree bit” in the git update-index manpage.



        The interface is not as convenient as SVN’s (e.g. there is no way to make a sparse checkout at the time of an initial clone), but the base functionality upon which simpler interfaces could be built is now available.






        share|improve this answer














        Git 1.7.0 has “sparse checkouts”. See
        “core.sparseCheckout” in the git config manpage,
        “Sparse checkout” in the git read-tree manpage, and
        “Skip-worktree bit” in the git update-index manpage.



        The interface is not as convenient as SVN’s (e.g. there is no way to make a sparse checkout at the time of an initial clone), but the base functionality upon which simpler interfaces could be built is now available.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jun 6 '12 at 4:42









        Community

        11




        11










        answered May 18 '10 at 21:15









        Chris Johnsen

        146k23171172




        146k23171172























            60














            This looks far simpler:



            git archive --remote=<repo_url> <branch> <path> | tar xvf -





            share|improve this answer



















            • 17




              When I do this on github I get fatal: Operation not supported by protocol. Unexpected end of command stream
              – Michael Fox
              Sep 25 '14 at 17:37








            • 4




              This works with bitbucket =)
              – Paul Rigor
              Oct 23 '14 at 5:05






            • 2




              If you're using github you can use svn export instead
              – 0sh
              Jul 5 '15 at 15:25






            • 2




              Won't work wiht Github --> Invalid command: 'git-upload-archive 'xxx/yyy.git'' You appear to be using ssh to clone a git:// URL. Make sure your core.gitProxy config option and the GIT_PROXY_COMMAND environment variable are NOT set. fatal: The remote end hung up unexpectedly
              – Nianliang
              Jul 14 '15 at 15:19






            • 2




              The reason why this doesn't work with GitHub: "We don't support using git-archive to pull an archive directly from GitHub. You can either clone the repo locally and run git-archive, or click on the Download ZIP button on the repo page." github.com/xuwupeng2000/capistrano-scm-gitcopy/issues/16
              – Donn Lee
              Aug 29 '16 at 23:17
















            60














            This looks far simpler:



            git archive --remote=<repo_url> <branch> <path> | tar xvf -





            share|improve this answer



















            • 17




              When I do this on github I get fatal: Operation not supported by protocol. Unexpected end of command stream
              – Michael Fox
              Sep 25 '14 at 17:37








            • 4




              This works with bitbucket =)
              – Paul Rigor
              Oct 23 '14 at 5:05






            • 2




              If you're using github you can use svn export instead
              – 0sh
              Jul 5 '15 at 15:25






            • 2




              Won't work wiht Github --> Invalid command: 'git-upload-archive 'xxx/yyy.git'' You appear to be using ssh to clone a git:// URL. Make sure your core.gitProxy config option and the GIT_PROXY_COMMAND environment variable are NOT set. fatal: The remote end hung up unexpectedly
              – Nianliang
              Jul 14 '15 at 15:19






            • 2




              The reason why this doesn't work with GitHub: "We don't support using git-archive to pull an archive directly from GitHub. You can either clone the repo locally and run git-archive, or click on the Download ZIP button on the repo page." github.com/xuwupeng2000/capistrano-scm-gitcopy/issues/16
              – Donn Lee
              Aug 29 '16 at 23:17














            60












            60








            60






            This looks far simpler:



            git archive --remote=<repo_url> <branch> <path> | tar xvf -





            share|improve this answer














            This looks far simpler:



            git archive --remote=<repo_url> <branch> <path> | tar xvf -






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Sep 2 '16 at 19:22









            Peter Mortensen

            13.5k1983111




            13.5k1983111










            answered Sep 10 '14 at 17:03









            ErichBSchulz

            9,71213840




            9,71213840








            • 17




              When I do this on github I get fatal: Operation not supported by protocol. Unexpected end of command stream
              – Michael Fox
              Sep 25 '14 at 17:37








            • 4




              This works with bitbucket =)
              – Paul Rigor
              Oct 23 '14 at 5:05






            • 2




              If you're using github you can use svn export instead
              – 0sh
              Jul 5 '15 at 15:25






            • 2




              Won't work wiht Github --> Invalid command: 'git-upload-archive 'xxx/yyy.git'' You appear to be using ssh to clone a git:// URL. Make sure your core.gitProxy config option and the GIT_PROXY_COMMAND environment variable are NOT set. fatal: The remote end hung up unexpectedly
              – Nianliang
              Jul 14 '15 at 15:19






            • 2




              The reason why this doesn't work with GitHub: "We don't support using git-archive to pull an archive directly from GitHub. You can either clone the repo locally and run git-archive, or click on the Download ZIP button on the repo page." github.com/xuwupeng2000/capistrano-scm-gitcopy/issues/16
              – Donn Lee
              Aug 29 '16 at 23:17














            • 17




              When I do this on github I get fatal: Operation not supported by protocol. Unexpected end of command stream
              – Michael Fox
              Sep 25 '14 at 17:37








            • 4




              This works with bitbucket =)
              – Paul Rigor
              Oct 23 '14 at 5:05






            • 2




              If you're using github you can use svn export instead
              – 0sh
              Jul 5 '15 at 15:25






            • 2




              Won't work wiht Github --> Invalid command: 'git-upload-archive 'xxx/yyy.git'' You appear to be using ssh to clone a git:// URL. Make sure your core.gitProxy config option and the GIT_PROXY_COMMAND environment variable are NOT set. fatal: The remote end hung up unexpectedly
              – Nianliang
              Jul 14 '15 at 15:19






            • 2




              The reason why this doesn't work with GitHub: "We don't support using git-archive to pull an archive directly from GitHub. You can either clone the repo locally and run git-archive, or click on the Download ZIP button on the repo page." github.com/xuwupeng2000/capistrano-scm-gitcopy/issues/16
              – Donn Lee
              Aug 29 '16 at 23:17








            17




            17




            When I do this on github I get fatal: Operation not supported by protocol. Unexpected end of command stream
            – Michael Fox
            Sep 25 '14 at 17:37






            When I do this on github I get fatal: Operation not supported by protocol. Unexpected end of command stream
            – Michael Fox
            Sep 25 '14 at 17:37






            4




            4




            This works with bitbucket =)
            – Paul Rigor
            Oct 23 '14 at 5:05




            This works with bitbucket =)
            – Paul Rigor
            Oct 23 '14 at 5:05




            2




            2




            If you're using github you can use svn export instead
            – 0sh
            Jul 5 '15 at 15:25




            If you're using github you can use svn export instead
            – 0sh
            Jul 5 '15 at 15:25




            2




            2




            Won't work wiht Github --> Invalid command: 'git-upload-archive 'xxx/yyy.git'' You appear to be using ssh to clone a git:// URL. Make sure your core.gitProxy config option and the GIT_PROXY_COMMAND environment variable are NOT set. fatal: The remote end hung up unexpectedly
            – Nianliang
            Jul 14 '15 at 15:19




            Won't work wiht Github --> Invalid command: 'git-upload-archive 'xxx/yyy.git'' You appear to be using ssh to clone a git:// URL. Make sure your core.gitProxy config option and the GIT_PROXY_COMMAND environment variable are NOT set. fatal: The remote end hung up unexpectedly
            – Nianliang
            Jul 14 '15 at 15:19




            2




            2




            The reason why this doesn't work with GitHub: "We don't support using git-archive to pull an archive directly from GitHub. You can either clone the repo locally and run git-archive, or click on the Download ZIP button on the repo page." github.com/xuwupeng2000/capistrano-scm-gitcopy/issues/16
            – Donn Lee
            Aug 29 '16 at 23:17




            The reason why this doesn't work with GitHub: "We don't support using git-archive to pull an archive directly from GitHub. You can either clone the repo locally and run git-archive, or click on the Download ZIP button on the repo page." github.com/xuwupeng2000/capistrano-scm-gitcopy/issues/16
            – Donn Lee
            Aug 29 '16 at 23:17











            43














            git clone --filter from Git 2.19



            This option will actually skip fetching unneeded objects from the server:



            git clone --depth 1 --no-checkout --filter=blob:none 
            "file://$(pwd)/server_repo" local_repo
            cd local_repo
            git checkout master -- mydir/


            The server should be configured with:



            git config --local uploadpack.allowfilter 1
            git config --local uploadpack.allowanysha1inwant 1


            An extension was made to the Git remote protocol to support this feature in v2.19.0, but there is no server support at that time. But it can already be locally tested.



            TODO: --filter=blob:none skips all blobs, but still fetches all tree objects. But on a normal repo, this should be tiny compared to the files themselves, so this is already good enough. Asked at: https://www.spinics.net/lists/git/msg342006.html Devs replied a --filter=tree:0 is in the works to do that.



            Remember that --depth 1 already implies --single-branch, see also: How do I clone a single branch in Git?



            file://$(path) is required to overcome git clone protocol shenanigans: How to shallow clone a local git repository with a relative path?



            The format of --filter is documented on man git-rev-list.



            Docs on Git tree:




            • https://github.com/git/git/blob/v2.19.0/Documentation/technical/partial-clone.txt

            • https://github.com/git/git/blob/v2.19.0/Documentation/rev-list-options.txt#L720

            • https://github.com/git/git/blob/v2.19.0/t/t5616-partial-clone.sh


            Test it out



            #!/usr/bin/env bash
            set -eu

            list-objects() (
            git rev-list --all --objects
            echo "master commit SHA: $(git log -1 --format="%H")"
            echo "mybranch commit SHA: $(git log -1 --format="%H")"
            git ls-tree master
            git ls-tree mybranch | grep mybranch
            git ls-tree master~ | grep root
            )

            # Reproducibility.
            export GIT_COMMITTER_NAME='a'
            export GIT_COMMITTER_EMAIL='a'
            export GIT_AUTHOR_NAME='a'
            export GIT_AUTHOR_EMAIL='a'
            export GIT_COMMITTER_DATE='2000-01-01T00:00:00+0000'
            export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'

            rm -rf server_repo local_repo
            mkdir server_repo
            cd server_repo

            # Create repo.
            git init --quiet
            git config --local uploadpack.allowfilter 1
            git config --local uploadpack.allowanysha1inwant 1

            # First commit.
            # Directories present in all branches.
            mkdir d1 d2
            printf 'd1/a' > ./d1/a
            printf 'd1/b' > ./d1/b
            printf 'd2/a' > ./d2/a
            printf 'd2/b' > ./d2/b
            # Present only in root.
            mkdir 'root'
            printf 'root' > ./root/root
            git add .
            git commit -m 'root' --quiet

            # Second commit only on master.
            git rm --quiet -r ./root
            mkdir 'master'
            printf 'master' > ./master/master
            git add .
            git commit -m 'master commit' --quiet

            # Second commit only on mybranch.
            git checkout -b mybranch --quiet master~
            git rm --quiet -r ./root
            mkdir 'mybranch'
            printf 'mybranch' > ./mybranch/mybranch
            git add .
            git commit -m 'mybranch commit' --quiet

            echo "# List and identify all objects"
            list-objects
            echo

            # Restore master.
            git checkout --quiet master
            cd ..

            # Clone. Don't checkout for now, only .git/ dir.
            git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repo
            cd local_repo

            # List missing objects from master.
            echo "# Missing objects after --no-checkout"
            git rev-list --all --quiet --objects --missing=print
            echo

            echo "# Git checkout fails without internet"
            mv ../server_repo ../server_repo.off
            ! git checkout master
            echo

            echo "# Git checkout fetches the missing directory from internet"
            mv ../server_repo.off ../server_repo
            git checkout master -- d1/
            echo

            echo "# Missing objects after checking out d1"
            git rev-list --all --quiet --objects --missing=print


            GitHub upstream.



            Output in Git v2.19.0:



            # List and identify all objects
            c6fcdfaf2b1462f809aecdad83a186eeec00f9c1
            fc5e97944480982cfc180a6d6634699921ee63ec
            7251a83be9a03161acde7b71a8fda9be19f47128
            62d67bce3c672fe2b9065f372726a11e57bade7e
            b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
            308150e8fddde043f3dbbb8573abb6af1df96e63 d1/a
            f70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b
            84de03c312dc741d0f2a66df7b2f168d823e122a d2
            0975df9b39e23c15f63db194df7f45c76528bccb d2/a
            41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b
            7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
            8b25206ff90e9432f6f1a8600f87a7bd695a24af master/master
            ef29f15c9a7c5417944cc09711b6a9ee51b01d89
            19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
            1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranch
            c3760bb1a0ece87cdbaf9a563c77a45e30a4e30e
            a0234da53ec608b54813b4271fbf00ba5318b99f root
            93ca1422a8da0a9effc465eccbcb17e23015542d root/root
            master commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
            mybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
            040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
            040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a d2
            040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
            040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
            040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f root

            # Missing objects after --no-checkout
            ?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
            ?8b25206ff90e9432f6f1a8600f87a7bd695a24af
            ?41484c13520fcbb6e7243a26fdb1fc9405c08520
            ?0975df9b39e23c15f63db194df7f45c76528bccb
            ?308150e8fddde043f3dbbb8573abb6af1df96e63

            # Git checkout fails without internet
            fatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repository
            fatal: Could not read from remote repository.

            Please make sure you have the correct access rights
            and the repository exists.

            # Git checkout fetches the missing directory from internet
            remote: Enumerating objects: 1, done.
            remote: Counting objects: 100% (1/1), done.
            remote: Total 1 (delta 0), reused 0 (delta 0)
            Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
            remote: Enumerating objects: 1, done.
            remote: Counting objects: 100% (1/1), done.
            remote: Total 1 (delta 0), reused 0 (delta 0)
            Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.

            # Missing objects after checking out d1
            ?8b25206ff90e9432f6f1a8600f87a7bd695a24af
            ?41484c13520fcbb6e7243a26fdb1fc9405c08520
            ?0975df9b39e23c15f63db194df7f45c76528bccb


            Conclusions: all blobs from outside of d1/ are missing. E.g. 0975df9b39e23c15f63db194df7f45c76528bccb, which is d2/b is not there after checking out d1/a.



            Note that root/root and mybranch/mybranch are also missing, but --depth 1 hides that from the list of missing files. If you remove --depth 1, then they show on the list of missing files.



            I have a dream



            This feature could revolutionize Git.



            Imagine having all the code base of your enterprise in a single repo without ugly third-party tools like repo.



            Imagine storing huge blobs directly in the repo without any ugly third party extensions.



            Imagine if GitHub would allow per file metadata like stars and permissions, so you can store all your personal stuff under a single repo.



            Imagine if submodules were treated exactly like regular directories: just request a tree SHA, and a DNS-like mechanism resolves your request, first looking on your local ~/.git, then first to closer servers (your enterprise's mirror / cache) and ending up on GitHub.






            share|improve this answer























            • I don't think introducing politics into StackOverflow is a good idea.
              – Weekend
              Dec 19 at 3:14










            • Hi @Weekend , see: github.com/cirosantilli/china-dictatorship/blob/… Let's move further discussion to meta or the issues on that repo.
              – Ciro Santilli 新疆改造中心 六四事件 法轮功
              Dec 19 at 8:50
















            43














            git clone --filter from Git 2.19



            This option will actually skip fetching unneeded objects from the server:



            git clone --depth 1 --no-checkout --filter=blob:none 
            "file://$(pwd)/server_repo" local_repo
            cd local_repo
            git checkout master -- mydir/


            The server should be configured with:



            git config --local uploadpack.allowfilter 1
            git config --local uploadpack.allowanysha1inwant 1


            An extension was made to the Git remote protocol to support this feature in v2.19.0, but there is no server support at that time. But it can already be locally tested.



            TODO: --filter=blob:none skips all blobs, but still fetches all tree objects. But on a normal repo, this should be tiny compared to the files themselves, so this is already good enough. Asked at: https://www.spinics.net/lists/git/msg342006.html Devs replied a --filter=tree:0 is in the works to do that.



            Remember that --depth 1 already implies --single-branch, see also: How do I clone a single branch in Git?



            file://$(path) is required to overcome git clone protocol shenanigans: How to shallow clone a local git repository with a relative path?



            The format of --filter is documented on man git-rev-list.



            Docs on Git tree:




            • https://github.com/git/git/blob/v2.19.0/Documentation/technical/partial-clone.txt

            • https://github.com/git/git/blob/v2.19.0/Documentation/rev-list-options.txt#L720

            • https://github.com/git/git/blob/v2.19.0/t/t5616-partial-clone.sh


            Test it out



            #!/usr/bin/env bash
            set -eu

            list-objects() (
            git rev-list --all --objects
            echo "master commit SHA: $(git log -1 --format="%H")"
            echo "mybranch commit SHA: $(git log -1 --format="%H")"
            git ls-tree master
            git ls-tree mybranch | grep mybranch
            git ls-tree master~ | grep root
            )

            # Reproducibility.
            export GIT_COMMITTER_NAME='a'
            export GIT_COMMITTER_EMAIL='a'
            export GIT_AUTHOR_NAME='a'
            export GIT_AUTHOR_EMAIL='a'
            export GIT_COMMITTER_DATE='2000-01-01T00:00:00+0000'
            export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'

            rm -rf server_repo local_repo
            mkdir server_repo
            cd server_repo

            # Create repo.
            git init --quiet
            git config --local uploadpack.allowfilter 1
            git config --local uploadpack.allowanysha1inwant 1

            # First commit.
            # Directories present in all branches.
            mkdir d1 d2
            printf 'd1/a' > ./d1/a
            printf 'd1/b' > ./d1/b
            printf 'd2/a' > ./d2/a
            printf 'd2/b' > ./d2/b
            # Present only in root.
            mkdir 'root'
            printf 'root' > ./root/root
            git add .
            git commit -m 'root' --quiet

            # Second commit only on master.
            git rm --quiet -r ./root
            mkdir 'master'
            printf 'master' > ./master/master
            git add .
            git commit -m 'master commit' --quiet

            # Second commit only on mybranch.
            git checkout -b mybranch --quiet master~
            git rm --quiet -r ./root
            mkdir 'mybranch'
            printf 'mybranch' > ./mybranch/mybranch
            git add .
            git commit -m 'mybranch commit' --quiet

            echo "# List and identify all objects"
            list-objects
            echo

            # Restore master.
            git checkout --quiet master
            cd ..

            # Clone. Don't checkout for now, only .git/ dir.
            git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repo
            cd local_repo

            # List missing objects from master.
            echo "# Missing objects after --no-checkout"
            git rev-list --all --quiet --objects --missing=print
            echo

            echo "# Git checkout fails without internet"
            mv ../server_repo ../server_repo.off
            ! git checkout master
            echo

            echo "# Git checkout fetches the missing directory from internet"
            mv ../server_repo.off ../server_repo
            git checkout master -- d1/
            echo

            echo "# Missing objects after checking out d1"
            git rev-list --all --quiet --objects --missing=print


            GitHub upstream.



            Output in Git v2.19.0:



            # List and identify all objects
            c6fcdfaf2b1462f809aecdad83a186eeec00f9c1
            fc5e97944480982cfc180a6d6634699921ee63ec
            7251a83be9a03161acde7b71a8fda9be19f47128
            62d67bce3c672fe2b9065f372726a11e57bade7e
            b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
            308150e8fddde043f3dbbb8573abb6af1df96e63 d1/a
            f70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b
            84de03c312dc741d0f2a66df7b2f168d823e122a d2
            0975df9b39e23c15f63db194df7f45c76528bccb d2/a
            41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b
            7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
            8b25206ff90e9432f6f1a8600f87a7bd695a24af master/master
            ef29f15c9a7c5417944cc09711b6a9ee51b01d89
            19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
            1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranch
            c3760bb1a0ece87cdbaf9a563c77a45e30a4e30e
            a0234da53ec608b54813b4271fbf00ba5318b99f root
            93ca1422a8da0a9effc465eccbcb17e23015542d root/root
            master commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
            mybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
            040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
            040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a d2
            040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
            040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
            040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f root

            # Missing objects after --no-checkout
            ?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
            ?8b25206ff90e9432f6f1a8600f87a7bd695a24af
            ?41484c13520fcbb6e7243a26fdb1fc9405c08520
            ?0975df9b39e23c15f63db194df7f45c76528bccb
            ?308150e8fddde043f3dbbb8573abb6af1df96e63

            # Git checkout fails without internet
            fatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repository
            fatal: Could not read from remote repository.

            Please make sure you have the correct access rights
            and the repository exists.

            # Git checkout fetches the missing directory from internet
            remote: Enumerating objects: 1, done.
            remote: Counting objects: 100% (1/1), done.
            remote: Total 1 (delta 0), reused 0 (delta 0)
            Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
            remote: Enumerating objects: 1, done.
            remote: Counting objects: 100% (1/1), done.
            remote: Total 1 (delta 0), reused 0 (delta 0)
            Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.

            # Missing objects after checking out d1
            ?8b25206ff90e9432f6f1a8600f87a7bd695a24af
            ?41484c13520fcbb6e7243a26fdb1fc9405c08520
            ?0975df9b39e23c15f63db194df7f45c76528bccb


            Conclusions: all blobs from outside of d1/ are missing. E.g. 0975df9b39e23c15f63db194df7f45c76528bccb, which is d2/b is not there after checking out d1/a.



            Note that root/root and mybranch/mybranch are also missing, but --depth 1 hides that from the list of missing files. If you remove --depth 1, then they show on the list of missing files.



            I have a dream



            This feature could revolutionize Git.



            Imagine having all the code base of your enterprise in a single repo without ugly third-party tools like repo.



            Imagine storing huge blobs directly in the repo without any ugly third party extensions.



            Imagine if GitHub would allow per file metadata like stars and permissions, so you can store all your personal stuff under a single repo.



            Imagine if submodules were treated exactly like regular directories: just request a tree SHA, and a DNS-like mechanism resolves your request, first looking on your local ~/.git, then first to closer servers (your enterprise's mirror / cache) and ending up on GitHub.






            share|improve this answer























            • I don't think introducing politics into StackOverflow is a good idea.
              – Weekend
              Dec 19 at 3:14










            • Hi @Weekend , see: github.com/cirosantilli/china-dictatorship/blob/… Let's move further discussion to meta or the issues on that repo.
              – Ciro Santilli 新疆改造中心 六四事件 法轮功
              Dec 19 at 8:50














            43












            43








            43






            git clone --filter from Git 2.19



            This option will actually skip fetching unneeded objects from the server:



            git clone --depth 1 --no-checkout --filter=blob:none 
            "file://$(pwd)/server_repo" local_repo
            cd local_repo
            git checkout master -- mydir/


            The server should be configured with:



            git config --local uploadpack.allowfilter 1
            git config --local uploadpack.allowanysha1inwant 1


            An extension was made to the Git remote protocol to support this feature in v2.19.0, but there is no server support at that time. But it can already be locally tested.



            TODO: --filter=blob:none skips all blobs, but still fetches all tree objects. But on a normal repo, this should be tiny compared to the files themselves, so this is already good enough. Asked at: https://www.spinics.net/lists/git/msg342006.html Devs replied a --filter=tree:0 is in the works to do that.



            Remember that --depth 1 already implies --single-branch, see also: How do I clone a single branch in Git?



            file://$(path) is required to overcome git clone protocol shenanigans: How to shallow clone a local git repository with a relative path?



            The format of --filter is documented on man git-rev-list.



            Docs on Git tree:




            • https://github.com/git/git/blob/v2.19.0/Documentation/technical/partial-clone.txt

            • https://github.com/git/git/blob/v2.19.0/Documentation/rev-list-options.txt#L720

            • https://github.com/git/git/blob/v2.19.0/t/t5616-partial-clone.sh


            Test it out



            #!/usr/bin/env bash
            set -eu

            list-objects() (
            git rev-list --all --objects
            echo "master commit SHA: $(git log -1 --format="%H")"
            echo "mybranch commit SHA: $(git log -1 --format="%H")"
            git ls-tree master
            git ls-tree mybranch | grep mybranch
            git ls-tree master~ | grep root
            )

            # Reproducibility.
            export GIT_COMMITTER_NAME='a'
            export GIT_COMMITTER_EMAIL='a'
            export GIT_AUTHOR_NAME='a'
            export GIT_AUTHOR_EMAIL='a'
            export GIT_COMMITTER_DATE='2000-01-01T00:00:00+0000'
            export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'

            rm -rf server_repo local_repo
            mkdir server_repo
            cd server_repo

            # Create repo.
            git init --quiet
            git config --local uploadpack.allowfilter 1
            git config --local uploadpack.allowanysha1inwant 1

            # First commit.
            # Directories present in all branches.
            mkdir d1 d2
            printf 'd1/a' > ./d1/a
            printf 'd1/b' > ./d1/b
            printf 'd2/a' > ./d2/a
            printf 'd2/b' > ./d2/b
            # Present only in root.
            mkdir 'root'
            printf 'root' > ./root/root
            git add .
            git commit -m 'root' --quiet

            # Second commit only on master.
            git rm --quiet -r ./root
            mkdir 'master'
            printf 'master' > ./master/master
            git add .
            git commit -m 'master commit' --quiet

            # Second commit only on mybranch.
            git checkout -b mybranch --quiet master~
            git rm --quiet -r ./root
            mkdir 'mybranch'
            printf 'mybranch' > ./mybranch/mybranch
            git add .
            git commit -m 'mybranch commit' --quiet

            echo "# List and identify all objects"
            list-objects
            echo

            # Restore master.
            git checkout --quiet master
            cd ..

            # Clone. Don't checkout for now, only .git/ dir.
            git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repo
            cd local_repo

            # List missing objects from master.
            echo "# Missing objects after --no-checkout"
            git rev-list --all --quiet --objects --missing=print
            echo

            echo "# Git checkout fails without internet"
            mv ../server_repo ../server_repo.off
            ! git checkout master
            echo

            echo "# Git checkout fetches the missing directory from internet"
            mv ../server_repo.off ../server_repo
            git checkout master -- d1/
            echo

            echo "# Missing objects after checking out d1"
            git rev-list --all --quiet --objects --missing=print


            GitHub upstream.



            Output in Git v2.19.0:



            # List and identify all objects
            c6fcdfaf2b1462f809aecdad83a186eeec00f9c1
            fc5e97944480982cfc180a6d6634699921ee63ec
            7251a83be9a03161acde7b71a8fda9be19f47128
            62d67bce3c672fe2b9065f372726a11e57bade7e
            b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
            308150e8fddde043f3dbbb8573abb6af1df96e63 d1/a
            f70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b
            84de03c312dc741d0f2a66df7b2f168d823e122a d2
            0975df9b39e23c15f63db194df7f45c76528bccb d2/a
            41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b
            7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
            8b25206ff90e9432f6f1a8600f87a7bd695a24af master/master
            ef29f15c9a7c5417944cc09711b6a9ee51b01d89
            19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
            1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranch
            c3760bb1a0ece87cdbaf9a563c77a45e30a4e30e
            a0234da53ec608b54813b4271fbf00ba5318b99f root
            93ca1422a8da0a9effc465eccbcb17e23015542d root/root
            master commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
            mybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
            040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
            040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a d2
            040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
            040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
            040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f root

            # Missing objects after --no-checkout
            ?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
            ?8b25206ff90e9432f6f1a8600f87a7bd695a24af
            ?41484c13520fcbb6e7243a26fdb1fc9405c08520
            ?0975df9b39e23c15f63db194df7f45c76528bccb
            ?308150e8fddde043f3dbbb8573abb6af1df96e63

            # Git checkout fails without internet
            fatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repository
            fatal: Could not read from remote repository.

            Please make sure you have the correct access rights
            and the repository exists.

            # Git checkout fetches the missing directory from internet
            remote: Enumerating objects: 1, done.
            remote: Counting objects: 100% (1/1), done.
            remote: Total 1 (delta 0), reused 0 (delta 0)
            Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
            remote: Enumerating objects: 1, done.
            remote: Counting objects: 100% (1/1), done.
            remote: Total 1 (delta 0), reused 0 (delta 0)
            Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.

            # Missing objects after checking out d1
            ?8b25206ff90e9432f6f1a8600f87a7bd695a24af
            ?41484c13520fcbb6e7243a26fdb1fc9405c08520
            ?0975df9b39e23c15f63db194df7f45c76528bccb


            Conclusions: all blobs from outside of d1/ are missing. E.g. 0975df9b39e23c15f63db194df7f45c76528bccb, which is d2/b is not there after checking out d1/a.



            Note that root/root and mybranch/mybranch are also missing, but --depth 1 hides that from the list of missing files. If you remove --depth 1, then they show on the list of missing files.



            I have a dream



            This feature could revolutionize Git.



            Imagine having all the code base of your enterprise in a single repo without ugly third-party tools like repo.



            Imagine storing huge blobs directly in the repo without any ugly third party extensions.



            Imagine if GitHub would allow per file metadata like stars and permissions, so you can store all your personal stuff under a single repo.



            Imagine if submodules were treated exactly like regular directories: just request a tree SHA, and a DNS-like mechanism resolves your request, first looking on your local ~/.git, then first to closer servers (your enterprise's mirror / cache) and ending up on GitHub.






            share|improve this answer














            git clone --filter from Git 2.19



            This option will actually skip fetching unneeded objects from the server:



            git clone --depth 1 --no-checkout --filter=blob:none 
            "file://$(pwd)/server_repo" local_repo
            cd local_repo
            git checkout master -- mydir/


            The server should be configured with:



            git config --local uploadpack.allowfilter 1
            git config --local uploadpack.allowanysha1inwant 1


            An extension was made to the Git remote protocol to support this feature in v2.19.0, but there is no server support at that time. But it can already be locally tested.



            TODO: --filter=blob:none skips all blobs, but still fetches all tree objects. But on a normal repo, this should be tiny compared to the files themselves, so this is already good enough. Asked at: https://www.spinics.net/lists/git/msg342006.html Devs replied a --filter=tree:0 is in the works to do that.



            Remember that --depth 1 already implies --single-branch, see also: How do I clone a single branch in Git?



            file://$(path) is required to overcome git clone protocol shenanigans: How to shallow clone a local git repository with a relative path?



            The format of --filter is documented on man git-rev-list.



            Docs on Git tree:




            • https://github.com/git/git/blob/v2.19.0/Documentation/technical/partial-clone.txt

            • https://github.com/git/git/blob/v2.19.0/Documentation/rev-list-options.txt#L720

            • https://github.com/git/git/blob/v2.19.0/t/t5616-partial-clone.sh


            Test it out



            #!/usr/bin/env bash
            set -eu

            list-objects() (
            git rev-list --all --objects
            echo "master commit SHA: $(git log -1 --format="%H")"
            echo "mybranch commit SHA: $(git log -1 --format="%H")"
            git ls-tree master
            git ls-tree mybranch | grep mybranch
            git ls-tree master~ | grep root
            )

            # Reproducibility.
            export GIT_COMMITTER_NAME='a'
            export GIT_COMMITTER_EMAIL='a'
            export GIT_AUTHOR_NAME='a'
            export GIT_AUTHOR_EMAIL='a'
            export GIT_COMMITTER_DATE='2000-01-01T00:00:00+0000'
            export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'

            rm -rf server_repo local_repo
            mkdir server_repo
            cd server_repo

            # Create repo.
            git init --quiet
            git config --local uploadpack.allowfilter 1
            git config --local uploadpack.allowanysha1inwant 1

            # First commit.
            # Directories present in all branches.
            mkdir d1 d2
            printf 'd1/a' > ./d1/a
            printf 'd1/b' > ./d1/b
            printf 'd2/a' > ./d2/a
            printf 'd2/b' > ./d2/b
            # Present only in root.
            mkdir 'root'
            printf 'root' > ./root/root
            git add .
            git commit -m 'root' --quiet

            # Second commit only on master.
            git rm --quiet -r ./root
            mkdir 'master'
            printf 'master' > ./master/master
            git add .
            git commit -m 'master commit' --quiet

            # Second commit only on mybranch.
            git checkout -b mybranch --quiet master~
            git rm --quiet -r ./root
            mkdir 'mybranch'
            printf 'mybranch' > ./mybranch/mybranch
            git add .
            git commit -m 'mybranch commit' --quiet

            echo "# List and identify all objects"
            list-objects
            echo

            # Restore master.
            git checkout --quiet master
            cd ..

            # Clone. Don't checkout for now, only .git/ dir.
            git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repo
            cd local_repo

            # List missing objects from master.
            echo "# Missing objects after --no-checkout"
            git rev-list --all --quiet --objects --missing=print
            echo

            echo "# Git checkout fails without internet"
            mv ../server_repo ../server_repo.off
            ! git checkout master
            echo

            echo "# Git checkout fetches the missing directory from internet"
            mv ../server_repo.off ../server_repo
            git checkout master -- d1/
            echo

            echo "# Missing objects after checking out d1"
            git rev-list --all --quiet --objects --missing=print


            GitHub upstream.



            Output in Git v2.19.0:



            # List and identify all objects
            c6fcdfaf2b1462f809aecdad83a186eeec00f9c1
            fc5e97944480982cfc180a6d6634699921ee63ec
            7251a83be9a03161acde7b71a8fda9be19f47128
            62d67bce3c672fe2b9065f372726a11e57bade7e
            b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
            308150e8fddde043f3dbbb8573abb6af1df96e63 d1/a
            f70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b
            84de03c312dc741d0f2a66df7b2f168d823e122a d2
            0975df9b39e23c15f63db194df7f45c76528bccb d2/a
            41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b
            7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
            8b25206ff90e9432f6f1a8600f87a7bd695a24af master/master
            ef29f15c9a7c5417944cc09711b6a9ee51b01d89
            19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
            1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranch
            c3760bb1a0ece87cdbaf9a563c77a45e30a4e30e
            a0234da53ec608b54813b4271fbf00ba5318b99f root
            93ca1422a8da0a9effc465eccbcb17e23015542d root/root
            master commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
            mybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
            040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
            040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a d2
            040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
            040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
            040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f root

            # Missing objects after --no-checkout
            ?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
            ?8b25206ff90e9432f6f1a8600f87a7bd695a24af
            ?41484c13520fcbb6e7243a26fdb1fc9405c08520
            ?0975df9b39e23c15f63db194df7f45c76528bccb
            ?308150e8fddde043f3dbbb8573abb6af1df96e63

            # Git checkout fails without internet
            fatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repository
            fatal: Could not read from remote repository.

            Please make sure you have the correct access rights
            and the repository exists.

            # Git checkout fetches the missing directory from internet
            remote: Enumerating objects: 1, done.
            remote: Counting objects: 100% (1/1), done.
            remote: Total 1 (delta 0), reused 0 (delta 0)
            Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
            remote: Enumerating objects: 1, done.
            remote: Counting objects: 100% (1/1), done.
            remote: Total 1 (delta 0), reused 0 (delta 0)
            Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.

            # Missing objects after checking out d1
            ?8b25206ff90e9432f6f1a8600f87a7bd695a24af
            ?41484c13520fcbb6e7243a26fdb1fc9405c08520
            ?0975df9b39e23c15f63db194df7f45c76528bccb


            Conclusions: all blobs from outside of d1/ are missing. E.g. 0975df9b39e23c15f63db194df7f45c76528bccb, which is d2/b is not there after checking out d1/a.



            Note that root/root and mybranch/mybranch are also missing, but --depth 1 hides that from the list of missing files. If you remove --depth 1, then they show on the list of missing files.



            I have a dream



            This feature could revolutionize Git.



            Imagine having all the code base of your enterprise in a single repo without ugly third-party tools like repo.



            Imagine storing huge blobs directly in the repo without any ugly third party extensions.



            Imagine if GitHub would allow per file metadata like stars and permissions, so you can store all your personal stuff under a single repo.



            Imagine if submodules were treated exactly like regular directories: just request a tree SHA, and a DNS-like mechanism resolves your request, first looking on your local ~/.git, then first to closer servers (your enterprise's mirror / cache) and ending up on GitHub.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Dec 12 at 16:24

























            answered Sep 11 at 6:32









            Ciro Santilli 新疆改造中心 六四事件 法轮功

            135k31527452




            135k31527452












            • I don't think introducing politics into StackOverflow is a good idea.
              – Weekend
              Dec 19 at 3:14










            • Hi @Weekend , see: github.com/cirosantilli/china-dictatorship/blob/… Let's move further discussion to meta or the issues on that repo.
              – Ciro Santilli 新疆改造中心 六四事件 法轮功
              Dec 19 at 8:50


















            • I don't think introducing politics into StackOverflow is a good idea.
              – Weekend
              Dec 19 at 3:14










            • Hi @Weekend , see: github.com/cirosantilli/china-dictatorship/blob/… Let's move further discussion to meta or the issues on that repo.
              – Ciro Santilli 新疆改造中心 六四事件 法轮功
              Dec 19 at 8:50
















            I don't think introducing politics into StackOverflow is a good idea.
            – Weekend
            Dec 19 at 3:14




            I don't think introducing politics into StackOverflow is a good idea.
            – Weekend
            Dec 19 at 3:14












            Hi @Weekend , see: github.com/cirosantilli/china-dictatorship/blob/… Let's move further discussion to meta or the issues on that repo.
            – Ciro Santilli 新疆改造中心 六四事件 法轮功
            Dec 19 at 8:50




            Hi @Weekend , see: github.com/cirosantilli/china-dictatorship/blob/… Let's move further discussion to meta or the issues on that repo.
            – Ciro Santilli 新疆改造中心 六四事件 法轮功
            Dec 19 at 8:50











            27














            It's not possible to clone subdirectory only with Git, but below are few workarounds.



            Filter branch



            You may want to rewrite the repository to look as if trunk/public_html/ had been its project root, and discard all other history (using filter-branch), try on already checkout branch:



            git filter-branch --subdirectory-filter trunk/public_html -- --all


            Notes: The -- that separates filter-branch options from revision options, and the --all to rewrite all branches and tags. All information including original commit times or merge information will be preserved. This command honors .git/info/grafts file and refs in the refs/replace/ namespace, so if you have any grafts or replacement refs defined, running this command will make them permanent.




            Warning! The rewritten history will have different object names for all the objects and will not converge with the original branch. You will not be able to easily push and distribute the rewritten branch on top of the original branch. Please do not use this command if you do not know the full implications, and avoid using it anyway, if a simple single commit would suffice to fix your problem.






            Sparse checkout



            Here are simple steps with sparse checkout approach which will populate the working directory sparsely, so you can tell Git which folder(s) or file(s) in the working directory are worth checking out.





            1. Clone repository as usual (--no-checkout is optional):



              git clone --no-checkout git@foo/bar.git
              cd bar


              You may skip this step, if you've your repository already cloned.



              Hint: For large repos, consider shallow clone (--depth 1) to checkout only latest revision or/and --single-branch only.




            2. Enable sparseCheckout option:



              git config core.sparseCheckout true



            3. Specify folder(s) for sparse checkout (without space at the end):



              echo "trunk/public_html/*"> .git/info/sparse-checkout


              or edit .git/info/sparse-checkout.




            4. Checkout the branch (e.g. master):



              git checkout master



            Now you should have selected folders in your current directory.



            You may consider symbolic links if you've too many levels of directories or filtering branch instead.









            share|improve this answer























            • Would Filter branch still allow you to pull?
              – sam
              Dec 17 '16 at 19:21






            • 2




              @sam: no. filter-branch would rewrite the parent commits so they'd have different SHA1 IDs, and thus your filtered tree would have no commits in common with the remote tree. git pull wouldn't know where to try to merge from.
              – Peter Cordes
              Jun 15 '17 at 4:06


















            27














            It's not possible to clone subdirectory only with Git, but below are few workarounds.



            Filter branch



            You may want to rewrite the repository to look as if trunk/public_html/ had been its project root, and discard all other history (using filter-branch), try on already checkout branch:



            git filter-branch --subdirectory-filter trunk/public_html -- --all


            Notes: The -- that separates filter-branch options from revision options, and the --all to rewrite all branches and tags. All information including original commit times or merge information will be preserved. This command honors .git/info/grafts file and refs in the refs/replace/ namespace, so if you have any grafts or replacement refs defined, running this command will make them permanent.




            Warning! The rewritten history will have different object names for all the objects and will not converge with the original branch. You will not be able to easily push and distribute the rewritten branch on top of the original branch. Please do not use this command if you do not know the full implications, and avoid using it anyway, if a simple single commit would suffice to fix your problem.






            Sparse checkout



            Here are simple steps with sparse checkout approach which will populate the working directory sparsely, so you can tell Git which folder(s) or file(s) in the working directory are worth checking out.





            1. Clone repository as usual (--no-checkout is optional):



              git clone --no-checkout git@foo/bar.git
              cd bar


              You may skip this step, if you've your repository already cloned.



              Hint: For large repos, consider shallow clone (--depth 1) to checkout only latest revision or/and --single-branch only.




            2. Enable sparseCheckout option:



              git config core.sparseCheckout true



            3. Specify folder(s) for sparse checkout (without space at the end):



              echo "trunk/public_html/*"> .git/info/sparse-checkout


              or edit .git/info/sparse-checkout.




            4. Checkout the branch (e.g. master):



              git checkout master



            Now you should have selected folders in your current directory.



            You may consider symbolic links if you've too many levels of directories or filtering branch instead.









            share|improve this answer























            • Would Filter branch still allow you to pull?
              – sam
              Dec 17 '16 at 19:21






            • 2




              @sam: no. filter-branch would rewrite the parent commits so they'd have different SHA1 IDs, and thus your filtered tree would have no commits in common with the remote tree. git pull wouldn't know where to try to merge from.
              – Peter Cordes
              Jun 15 '17 at 4:06
















            27












            27








            27






            It's not possible to clone subdirectory only with Git, but below are few workarounds.



            Filter branch



            You may want to rewrite the repository to look as if trunk/public_html/ had been its project root, and discard all other history (using filter-branch), try on already checkout branch:



            git filter-branch --subdirectory-filter trunk/public_html -- --all


            Notes: The -- that separates filter-branch options from revision options, and the --all to rewrite all branches and tags. All information including original commit times or merge information will be preserved. This command honors .git/info/grafts file and refs in the refs/replace/ namespace, so if you have any grafts or replacement refs defined, running this command will make them permanent.




            Warning! The rewritten history will have different object names for all the objects and will not converge with the original branch. You will not be able to easily push and distribute the rewritten branch on top of the original branch. Please do not use this command if you do not know the full implications, and avoid using it anyway, if a simple single commit would suffice to fix your problem.






            Sparse checkout



            Here are simple steps with sparse checkout approach which will populate the working directory sparsely, so you can tell Git which folder(s) or file(s) in the working directory are worth checking out.





            1. Clone repository as usual (--no-checkout is optional):



              git clone --no-checkout git@foo/bar.git
              cd bar


              You may skip this step, if you've your repository already cloned.



              Hint: For large repos, consider shallow clone (--depth 1) to checkout only latest revision or/and --single-branch only.




            2. Enable sparseCheckout option:



              git config core.sparseCheckout true



            3. Specify folder(s) for sparse checkout (without space at the end):



              echo "trunk/public_html/*"> .git/info/sparse-checkout


              or edit .git/info/sparse-checkout.




            4. Checkout the branch (e.g. master):



              git checkout master



            Now you should have selected folders in your current directory.



            You may consider symbolic links if you've too many levels of directories or filtering branch instead.









            share|improve this answer














            It's not possible to clone subdirectory only with Git, but below are few workarounds.



            Filter branch



            You may want to rewrite the repository to look as if trunk/public_html/ had been its project root, and discard all other history (using filter-branch), try on already checkout branch:



            git filter-branch --subdirectory-filter trunk/public_html -- --all


            Notes: The -- that separates filter-branch options from revision options, and the --all to rewrite all branches and tags. All information including original commit times or merge information will be preserved. This command honors .git/info/grafts file and refs in the refs/replace/ namespace, so if you have any grafts or replacement refs defined, running this command will make them permanent.




            Warning! The rewritten history will have different object names for all the objects and will not converge with the original branch. You will not be able to easily push and distribute the rewritten branch on top of the original branch. Please do not use this command if you do not know the full implications, and avoid using it anyway, if a simple single commit would suffice to fix your problem.






            Sparse checkout



            Here are simple steps with sparse checkout approach which will populate the working directory sparsely, so you can tell Git which folder(s) or file(s) in the working directory are worth checking out.





            1. Clone repository as usual (--no-checkout is optional):



              git clone --no-checkout git@foo/bar.git
              cd bar


              You may skip this step, if you've your repository already cloned.



              Hint: For large repos, consider shallow clone (--depth 1) to checkout only latest revision or/and --single-branch only.




            2. Enable sparseCheckout option:



              git config core.sparseCheckout true



            3. Specify folder(s) for sparse checkout (without space at the end):



              echo "trunk/public_html/*"> .git/info/sparse-checkout


              or edit .git/info/sparse-checkout.




            4. Checkout the branch (e.g. master):



              git checkout master



            Now you should have selected folders in your current directory.



            You may consider symbolic links if you've too many levels of directories or filtering branch instead.










            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jul 21 '16 at 22:12

























            answered Mar 22 '16 at 23:06









            kenorb

            64.7k27388391




            64.7k27388391












            • Would Filter branch still allow you to pull?
              – sam
              Dec 17 '16 at 19:21






            • 2




              @sam: no. filter-branch would rewrite the parent commits so they'd have different SHA1 IDs, and thus your filtered tree would have no commits in common with the remote tree. git pull wouldn't know where to try to merge from.
              – Peter Cordes
              Jun 15 '17 at 4:06




















            • Would Filter branch still allow you to pull?
              – sam
              Dec 17 '16 at 19:21






            • 2




              @sam: no. filter-branch would rewrite the parent commits so they'd have different SHA1 IDs, and thus your filtered tree would have no commits in common with the remote tree. git pull wouldn't know where to try to merge from.
              – Peter Cordes
              Jun 15 '17 at 4:06


















            Would Filter branch still allow you to pull?
            – sam
            Dec 17 '16 at 19:21




            Would Filter branch still allow you to pull?
            – sam
            Dec 17 '16 at 19:21




            2




            2




            @sam: no. filter-branch would rewrite the parent commits so they'd have different SHA1 IDs, and thus your filtered tree would have no commits in common with the remote tree. git pull wouldn't know where to try to merge from.
            – Peter Cordes
            Jun 15 '17 at 4:06






            @sam: no. filter-branch would rewrite the parent commits so they'd have different SHA1 IDs, and thus your filtered tree would have no commits in common with the remote tree. git pull wouldn't know where to try to merge from.
            – Peter Cordes
            Jun 15 '17 at 4:06













            10














            I just wrote a script for GitHub.



            Usage:



            python get_git_sub_dir.py path/to/sub/dir <RECURSIVE>





            share|improve this answer



















            • 11




              FYI, that's for GitHub only.
              – Sz.
              May 25 '14 at 14:49






            • 8




              And apparently this is for downloading a directory, not cloning a piece of a repo with all its metadata... right?
              – LarsH
              Oct 15 '15 at 19:18
















            10














            I just wrote a script for GitHub.



            Usage:



            python get_git_sub_dir.py path/to/sub/dir <RECURSIVE>





            share|improve this answer



















            • 11




              FYI, that's for GitHub only.
              – Sz.
              May 25 '14 at 14:49






            • 8




              And apparently this is for downloading a directory, not cloning a piece of a repo with all its metadata... right?
              – LarsH
              Oct 15 '15 at 19:18














            10












            10








            10






            I just wrote a script for GitHub.



            Usage:



            python get_git_sub_dir.py path/to/sub/dir <RECURSIVE>





            share|improve this answer














            I just wrote a script for GitHub.



            Usage:



            python get_git_sub_dir.py path/to/sub/dir <RECURSIVE>






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Sep 2 '16 at 19:22









            Peter Mortensen

            13.5k1983111




            13.5k1983111










            answered Jan 23 '14 at 18:49









            david_adler

            2,24422046




            2,24422046








            • 11




              FYI, that's for GitHub only.
              – Sz.
              May 25 '14 at 14:49






            • 8




              And apparently this is for downloading a directory, not cloning a piece of a repo with all its metadata... right?
              – LarsH
              Oct 15 '15 at 19:18














            • 11




              FYI, that's for GitHub only.
              – Sz.
              May 25 '14 at 14:49






            • 8




              And apparently this is for downloading a directory, not cloning a piece of a repo with all its metadata... right?
              – LarsH
              Oct 15 '15 at 19:18








            11




            11




            FYI, that's for GitHub only.
            – Sz.
            May 25 '14 at 14:49




            FYI, that's for GitHub only.
            – Sz.
            May 25 '14 at 14:49




            8




            8




            And apparently this is for downloading a directory, not cloning a piece of a repo with all its metadata... right?
            – LarsH
            Oct 15 '15 at 19:18




            And apparently this is for downloading a directory, not cloning a piece of a repo with all its metadata... right?
            – LarsH
            Oct 15 '15 at 19:18











            5














            Here's a shell script I wrote for the use case of a single subdirectory sparse checkout



            coSubDir.sh



            localRepo=$1
            remoteRepo=$2
            subDir=$3


            # Create local repository for subdirectory checkout, make it hidden to avoid having to drill down to the subfolder
            mkdir ./.$localRepo
            cd ./.$localRepo
            git init
            git remote add -f origin $remoteRepo
            git config core.sparseCheckout true

            # Add the subdirectory of interest to the sparse checkout.
            echo $subDir >> .git/info/sparse-checkout

            git pull origin master

            # Create convenience symlink to the subdirectory of interest
            cd ..
            ln -s ./.$localRepo$subDir $localRepo





            share|improve this answer

















            • 1




              Nice script, only something which should be fixed is the symlink, should be ln -s ./.$localRepo/$subDir $localRepo instead of ln -s ./.$localRepo$subDir $localRepo
              – valentin_nasta
              Mar 16 at 8:33
















            5














            Here's a shell script I wrote for the use case of a single subdirectory sparse checkout



            coSubDir.sh



            localRepo=$1
            remoteRepo=$2
            subDir=$3


            # Create local repository for subdirectory checkout, make it hidden to avoid having to drill down to the subfolder
            mkdir ./.$localRepo
            cd ./.$localRepo
            git init
            git remote add -f origin $remoteRepo
            git config core.sparseCheckout true

            # Add the subdirectory of interest to the sparse checkout.
            echo $subDir >> .git/info/sparse-checkout

            git pull origin master

            # Create convenience symlink to the subdirectory of interest
            cd ..
            ln -s ./.$localRepo$subDir $localRepo





            share|improve this answer

















            • 1




              Nice script, only something which should be fixed is the symlink, should be ln -s ./.$localRepo/$subDir $localRepo instead of ln -s ./.$localRepo$subDir $localRepo
              – valentin_nasta
              Mar 16 at 8:33














            5












            5








            5






            Here's a shell script I wrote for the use case of a single subdirectory sparse checkout



            coSubDir.sh



            localRepo=$1
            remoteRepo=$2
            subDir=$3


            # Create local repository for subdirectory checkout, make it hidden to avoid having to drill down to the subfolder
            mkdir ./.$localRepo
            cd ./.$localRepo
            git init
            git remote add -f origin $remoteRepo
            git config core.sparseCheckout true

            # Add the subdirectory of interest to the sparse checkout.
            echo $subDir >> .git/info/sparse-checkout

            git pull origin master

            # Create convenience symlink to the subdirectory of interest
            cd ..
            ln -s ./.$localRepo$subDir $localRepo





            share|improve this answer












            Here's a shell script I wrote for the use case of a single subdirectory sparse checkout



            coSubDir.sh



            localRepo=$1
            remoteRepo=$2
            subDir=$3


            # Create local repository for subdirectory checkout, make it hidden to avoid having to drill down to the subfolder
            mkdir ./.$localRepo
            cd ./.$localRepo
            git init
            git remote add -f origin $remoteRepo
            git config core.sparseCheckout true

            # Add the subdirectory of interest to the sparse checkout.
            echo $subDir >> .git/info/sparse-checkout

            git pull origin master

            # Create convenience symlink to the subdirectory of interest
            cd ..
            ln -s ./.$localRepo$subDir $localRepo






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Mar 8 at 19:39









            jxramos

            1,67111942




            1,67111942








            • 1




              Nice script, only something which should be fixed is the symlink, should be ln -s ./.$localRepo/$subDir $localRepo instead of ln -s ./.$localRepo$subDir $localRepo
              – valentin_nasta
              Mar 16 at 8:33














            • 1




              Nice script, only something which should be fixed is the symlink, should be ln -s ./.$localRepo/$subDir $localRepo instead of ln -s ./.$localRepo$subDir $localRepo
              – valentin_nasta
              Mar 16 at 8:33








            1




            1




            Nice script, only something which should be fixed is the symlink, should be ln -s ./.$localRepo/$subDir $localRepo instead of ln -s ./.$localRepo$subDir $localRepo
            – valentin_nasta
            Mar 16 at 8:33




            Nice script, only something which should be fixed is the symlink, should be ln -s ./.$localRepo/$subDir $localRepo instead of ln -s ./.$localRepo$subDir $localRepo
            – valentin_nasta
            Mar 16 at 8:33





            protected by Tunaki May 24 '16 at 22:30



            Thank you for your interest in this question.
            Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



            Would you like to answer one of these unanswered questions instead?



            Popular posts from this blog

            Xamarin.iOS Cant Deploy on Iphone

            Glorious Revolution

            Dulmage-Mendelsohn matrix decomposition in Python