我该如何从git存储库克隆、提取或稀疏检出单个目录或目录列表?

15
我如何从Git存储库中克隆、提取或稀疏检出单个文件、目录或文件/目录列表,避免下载整个历史记录或至少将历史记录下载保持在最小限度?以下是其他类似问题的参考:这些类似的问题早已被问过,而Git也不断发展,导致了大量不同的答案,有些更好,有些更差,具体取决于所考虑的Git版本。问题在于,这些问题中没有一个答案满足所有这些问题的所有要求,这意味着您必须阅读所有答案并在脑海中编译自己的答案,最终满足所有要求。本问题扩展了前面提到的问题,对所有其他问题的要求进行了更灵活和严格的限制。所以,再次提问:我如何从Git存储库中克隆、提取或稀疏检出单个文件、目录或文件/目录列表,避免下载整个历史记录或至少将历史记录下载保持在最小限度?

这个回答解决了你的问题吗?如何仅克隆Git存储库的子目录? - phd
https://stackoverflow.com/search?q=%5Bgit%5D+shallow+clone+sparse+checkout - phd
@phd:不完全是。你提到的答案中我们可以看到的函数会拉取所有分支的完整历史记录。我的实现只拉取一个分支的历史记录,并且据我所知仅拉取历史记录的顶端。 - Richard Gomes
@phd:你的第二条评论链接已经损坏。 - Richard Gomes
在链接的重复问题中有很多答案。其中提到了 git clone --depthgit clone --filter。第二个搜索链接对我有效。 - phd
@phd:我已经编辑了这个问题,解释了它的需求,并引用了其他类似的问题。然而,这个问题最重要的好处是提供一个完整、自包含、经过测试、文档完备、具有使用示例并满足之前所有问题和本问题引入的更多需求的答案。 - Richard Gomes
2个回答

12

下面这个bash函数可以解决问题。

function git_sparse_checkout {
    # git repository, e.g.: http://github.com/frgomes/bash-scripts
    local url=$1
    # directory where the repository will be downloaded, e.g.: ./build/sources
    local dir=$2
    # repository name, in general taken from the url, e.g.: bash-scripts
    local prj=$3
    # tag, e.g.: master
    local tag=$4
    [[ ( -z "$url" ) || ( -z "$dir" ) || ( -z "$prj" ) || ( -z "$tag" ) ]] && \
        echo "ERROR: git_sparse_checkout: invalid arguments" && \
        return 1
    shift; shift; shift; shift

    # Note: any remaining arguments after these above are considered as a
    # list of files or directories to be downloaded.
    
    mkdir -p ${dir}
    if [ ! -d ${dir}/${prj} ] ;then
        mkdir -p ${dir}/${prj}
        pushd ${dir}/${prj}
        git init
        git config core.sparseCheckout true
        local path="" # local scope
        for path in $* ;do
            echo "${path}" >> .git/info/sparse-checkout
        done
        git remote add origin ${url}
        git fetch --depth=1 origin ${tag}
        git checkout ${tag}
        popd
    fi
}

这是一个示例,说明如何使用它:

function example_download_scripts {
  url=http://github.com/frgomes/bash-scripts
  dir=$(pwd)/sources
  prj=bash-scripts
  tag=master
  git_sparse_checkout $url $dir $prj $tag "user-install/*" sysadmin-install/install-emacs.sh
}
在上面的示例中,请注意目录必须以 /* 结尾,并且必须在单引号或双引号之间。 更新:改进版可在此处找到:https://github.com/frgomes/bash-scripts/blob/master/bin/git_sparse_checkout

0

如果你只想要没有历史记录的文件,你可以使用svn:

SUBDIR=foo
svn export https://github.com/repository.git/trunk/$SUBDIR

svn?OP 问的是 git。也许这在 GitHub 上可行,我不知道。 - towi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接