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

前端 未结 18 2893
时光说笑
时光说笑 2020-11-21 04:33

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

/finisht
/static

When this was in SVN, /finisht was chec

相关标签:
18条回答
  • 2020-11-21 05:07

    I just wrote a script for GitHub.

    Usage:

    python get_git_sub_dir.py path/to/sub/dir <RECURSIVE>
    
    0 讨论(0)
  • 2020-11-21 05:07

    Just to clarify some of the great answers here, the steps outlined in many of the answers assume that you already have a remote repository somewhere.

    Given: an existing git repository, e.g. git@github.com:some-user/full-repo.git, with one or more directories that you wish to pull independently of the rest of the repo, e.g. directories named app1 and app2

    Assuming you have a git repository as the above...

    Then: you can run steps like the following to pull only specific directories from that larger repo:

    mkdir app1
    cd app1
    git init
    git remote add origin git@github.com:some-user/full-repo.git
    git config core.sparsecheckout true
    echo "app1/" >> .git/info/sparse-checkout
    git pull origin master
    

    I mistakenly thought that the sparse-checkout options had to be set on the original repository: this is not the case. You define which directories you want locally, prior to pulling from the remote. Hope this clarification helps someone else.

    0 讨论(0)
  • 2020-11-21 05:07

    So i tried everything in this tread and nothing worked for me ... Turns out that on version 2.24 of Git (the one that comes with cpanel at the time of this answer), you don't need to do this

    echo "wpm/*" >> .git/info/sparse-checkout
    

    all you need is the folder name

    wpm/*
    

    So in short you do this

    git config core.sparsecheckout true
    

    you then edit the .git/info/sparse-checkout and add the folder names (one per line) with /* at the end to get subfolders and files

    wpm/*
    

    Save and run the checkout command

    git checkout master
    

    The result was the expected folder from my repo and nothing else Upvote if this worked for you

    0 讨论(0)
  • 2020-11-21 05:09

    EDIT: As of Git 2.19, this is finally possible, as can be seen in this answer.

    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.

    0 讨论(0)
  • 2020-11-21 05:11

    I wrote a .gitconfig [alias] for performing a "sparse checkout". Check it out (no pun intended):

    On Windows run in cmd.exe

    git config --global alias.sparse-checkout "!f(){ [ $# -eq 2 ] && L=${1##*/} L=${L%.git} || L=$2; mkdir -p \"$L/.git/info\" && cd \"$L\" && git init --template= && git remote add origin \"$1\" && git config core.sparseCheckout 1; [ $# -eq 2 ] && echo \"$2\" >> .git/info/sparse-checkout || { shift 2; for i; do echo $i >> .git/info/sparse-checkout; done }; git pull --depth 1 origin master;};f"
    

    Otherwise:

    git config --global alias.sparse-checkout '!f(){ [ $# -eq 2 ] && L=${1##*/} L=${L%.git} || L=$2; mkdir -p "$L/.git/info" && cd "$L" && git init --template= && git remote add origin "$1" && git config core.sparseCheckout 1; [ $# -eq 2 ] && echo "$2" >> .git/info/sparse-checkout || { shift 2; for i; do echo $i >> .git/info/sparse-checkout; done }; git pull --depth 1 origin master;};f'
    

    Usage:

    # Makes a directory ForStackExchange with Plug checked out
    git sparse-checkout https://github.com/YenForYang/ForStackExchange Plug
    
    # To do more than 1 directory, you have to specify the local directory:
    git sparse-checkout https://github.com/YenForYang/ForStackExchange ForStackExchange Plug Folder
    

    The git config commands are 'minified' for convenience and storage, but here is the alias expanded:

    # Note the --template= is for disabling templates.
    # Feel free to remove it if you don't have issues with them (like I did)
    # `mkdir` makes the .git/info directory ahead of time, as I've found it missing sometimes for some reason
    f(){
        [ "$#" -eq 2 ] && L="${1##*/}" L=${L%.git} || L=$2;
        mkdir -p "$L/.git/info"
            && cd "$L"
            && git init --template=
            && git remote add origin "$1"
            && git config core.sparseCheckout 1;
        [ "$#" -eq 2 ]
            && echo "$2" >> .git/info/sparse-checkout
            || {
                shift 2;
                for i; do
                    echo $i >> .git/info/sparse-checkout;
                done
            };
        git pull --depth 1 origin master;
    };
    f
    
    0 讨论(0)
  • 2020-11-21 05:15

    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
    
    0 讨论(0)
提交回复
热议问题