如何从GitHub上托管的远程Git repo中仅下载特定文件夹或目录?

举个GitHub repo的例子:

git@github.com:foobar/Test.git

其目录结构:

Test/
├── foo/ 
│   ├── a.py
│   └── b.py   
└── bar/
    ├── c.py
    └── d.py

我只想下载foo文件夹,而不是克隆整个测试项目。


当前回答

使用此函数,第一个参数是文件夹的url,第二个参数是下载文件夹的位置:

function github-dir() {
    svn export "$(sed 's/tree\/master/trunk/' <<< "$1")" "$2"  
}

其他回答

你不能;不同于Subversion,每个子目录都可以单独检出,Git在整个存储库的基础上运行。

对于需要更细粒度访问的项目,可以使用子模块——每个子模块都是一个单独的Git项目,因此可以单独克隆。

可以想象,Git前端(例如GitHub的web界面或gitweb)可以选择为您提供一个界面来提取给定的文件夹,但据我所知,他们中没有一个这样做(尽管他们确实允许您下载单个文件,所以如果文件夹不包含太多文件,这是一个选项)

编辑-GitHub实际上提供了通过SVN的访问,这将允许您执行此操作(根据评论)。看见https://github.com/blog/1438-improved-svn-here-to-stay-old-svn-going-away有关如何执行此操作的最新说明

我使用linux,所以把它放在~/.bashrc中,甚至称为:D$HOME/.bashrc

git-dowloadfolder(){
a="$1"
svn checkout ${a/tree\/master/trunk}

}

然后用

source ~/.bashrc 

然后将其与git downloadfolder blablabla:D一起使用

2019年总结

有多种方法来处理这一点,这取决于您是否希望手动或以编程方式执行此操作。

下面总结了四个选项。对于那些喜欢更实际的解释的人,我制作了一个YouTube视频:从GitHub下载个人文件和文件夹。

此外,对于那些需要从GitHub下载单个文件(而不是文件夹)的人,我在StackOverflow上发布了类似的答案。


1.GitHub用户界面

存储库主页上有一个下载按钮。当然,这将下载整个repo,之后您需要解压缩下载,然后手动拖出所需的特定文件夹。

2.第三方工具

有多种浏览器扩展和web应用可以处理这一问题,DownGit就是其中之一。只需将GitHub URL粘贴到文件夹(例如。https://github.com/babel/babel-eslint/tree/master/lib)然后按下“下载”按钮。

3.子版本

GitHub不支持git存档(允许我们下载特定文件夹的git功能)。然而,GitHub支持多种Subversion功能,我们可以使用其中一种功能。Subversion是一种版本控制系统(git的替代品)。您需要安装Subversion。获取要下载的文件夹的GitHub URL。不过,您需要修改此URL。您需要指向存储库的链接,后跟单词“trunk”,并以指向嵌套文件夹的路径结尾。换句话说,使用与我前面提到的相同的文件夹链接示例,我们将用“trunk”替换“tree/master”。最后,打开一个终端,导航到要下载内容的目录,输入以下命令(用您构建的URL替换URL):svn exporthttps://github.com/babel/babel-eslint/trunk/lib,然后按enter键。

4.GitHub API

如果您想以编程方式完成此任务,这是您需要的解决方案。这实际上是DownGit在幕后使用的。使用GitHub的REST API,编写一个脚本,向内容端点发出GET请求。端点的构造如下:https://api.github.com/repos/:owner/:repo/contents/:path.替换占位符后,示例端点为:https://api.github.com/repos/babel/babel-eslint/contents/lib.这将为该文件夹中存在的所有内容提供JSON数据。数据包含您所需的一切,包括内容是否是文件夹或文件,如果是文件,则包含下载URL,如果是文件夹,则包含API端点(以便您可以获取该文件夹的数据)。使用这些数据,脚本可以递归地遍历目标文件夹中的所有内容,为嵌套文件夹创建文件夹,并下载每个文件夹的所有文件。查看DownGit的代码以获得灵感。

您可以简单地下载目录树:

git archive --remote git@github.com:foobar/Test.git HEAD:foo | tar xf -

但如果你想检查一下,并且能够提交并将它们推回去,那么你就不能这样做。

这是我用git v2.25.0做的,也是用v2.26.2测试的。这个技巧不适用于v2.30.1

TLDR

git clone --no-checkout --filter=tree:0 https://github.com/opencv/opencv
cd opencv

# requires git 2.25.x to 2.26.2
git sparse-checkout set data/haarcascades

您可以使用Docker来避免安装特定版本的git

git clone --no-checkout --filter=tree:0 https://github.com/opencv/opencv
cd opencv

# requires git 2.25.x to 2.26.2
docker run --rm -it -v $PWD/:/code/ --workdir=/code/ alpine/git:v2.26.2 sparse-checkout set data/haarcascades

完整解决方案

# bare minimum clone of opencv
$ git clone --no-checkout --filter=tree:0 https://github.com/opencv/opencv
...
Resolving deltas: 100% (529/529), done.

# Downloaded only ~7.3MB , takes ~3 seconds
# du = disk usage, -s = summary, -h = human-readable
$ du -sh opencv
7.3M    opencv/

# Set target dir
$ cd opencv
$ git sparse-checkout set data/haarcascades
...
Updating files: 100% (17/17), done.
# Takes ~10 seconds, depending on your specs

# View downloaded files
$ du -sh data/haarcascades/
9.4M    data/haarcascades/
$ ls data/haarcascades/
haarcascade_eye.xml                      haarcascade_frontalface_alt2.xml      haarcascade_licence_plate_rus_16stages.xml  haarcascade_smile.xml
haarcascade_eye_tree_eyeglasses.xml      haarcascade_frontalface_alt_tree.xml  haarcascade_lowerbody.xml                   haarcascade_upperbody.xml
haarcascade_frontalcatface.xml           haarcascade_frontalface_default.xml   haarcascade_profileface.xml
haarcascade_frontalcatface_extended.xml  haarcascade_fullbody.xml              haarcascade_righteye_2splits.xml
haarcascade_frontalface_alt.xml          haarcascade_lefteye_2splits.xml       haarcascade_russian_plate_number.xml

工具书类

git稀疏签出日志git稀疏签出文档gitfilter props文档