从GitHub仓库下载单个文件夹或目录

从GitHub仓库下载单个文件夹或目录

技术背景

在开发过程中,有时我们只需要GitHub仓库中的某个特定文件夹,而不是整个仓库。然而,Git本身并不支持直接检出单个目录,不过有多种方法可以实现从GitHub仓库下载单个文件夹或目录。

实现步骤

方法一:使用社区工具

  • Download Directory:该工具已集成到优秀的 Chrome 扩展 Refined GitHub 中,在 GitHub 网页用户界面中作为一个按钮存在。使用时,直接点击按钮即可下载指定文件夹。
  • GitZip:有 Chrome 扩展、Edge 扩展和 Firefox 插件版本。
    1. 浏览任何 GitHub 仓库页面。
    2. 有两种下载方式:
      • 选择项目:默认情况下,可双击项目或勾选项目前面的复选框,然后点击页面右下角的下载按钮。
      • 在上下文菜单中操作:点击“GitZip Download” -> “Whole Repository” 或 “Current Folder”;将鼠标光标移到项目上,点击 “GitZip Download” -> “Selected Folder/File”;完成 2 - 1 - 1 操作后,点击 “GitZip Download” -> “Checked Items”。
    3. 查看进度仪表盘,等待浏览器触发下载。
    4. 获取 ZIP 文件。
    5. 获取令牌:点击浏览器上的 GitZip 扩展图标,点击 “Get Token” 旁边的 “Normal” 或 “Private” 链接,在 GitHub 认证页面授权 GitZip 权限,返回初始的仓库页面,继续使用。
  • DownGit:直接访问 DownGit,输入 GitHub 公共目录或文件的 URL,即可直接下载或创建下载链接。还可配置下载文件的属性,详细用法见 这里

方法二:使用 Subversion(SVN)(已不支持)

GitHub 曾支持通过 Subversion(SVN)下载特定文件夹,但自 2024 年 1 月 8 日起,SVN 支持已被移除。以下是之前的操作步骤:

  1. 导航到要下载的文件夹,例如要从 master 分支下载 /test 文件夹。
  2. 修改 URL 以用于 Subversion,将 tree/master 替换为 trunk。例如,将 https://github.com/lodash/lodash/tree/master/test 替换为 https://github.com/lodash/lodash/trunk/test
  3. 打开命令行,使用 SVN 下载文件夹:
1
svn checkout https://github.com/lodash/lodash/trunk/test

由于 GitHub 转换大型仓库可能需要长达 30 秒,所以可能不会立即看到活动,需耐心等待。

方法三:使用 GitHub 的 Visual Studio Code 编辑器

  1. 访问任何仓库,例如 https://github.com/RespiraWorks/Ventilator/tree/master/software
  2. 按下 . 键或在 URL 中将 .com 替换为 .dev,在 GitHub 的内部编辑器中打开仓库。
  3. Explorer 面板(左侧,或按 Ctrl + Shift + E)中,右键单击所需的文件/文件夹,选择 Download
  4. Select Folder 对话框中,选择磁盘上要保存所选文件/文件夹的目录。

方法四:使用 git clone --filter

例如,要克隆 https://github.com/cirosantilli/test-git-partial-clone-big-small-no-bigtree 仓库中 small/ 子目录所需的对象,可执行以下命令:

1
2
3
4
git clone -n --depth=1 --filter=tree:0 https://github.com/cirosantilli/test-git-partial-clone-big-small-no-bigtree
cd test-git-partial-clone-big-small-no-bigtree
git sparse-checkout set --no-cone /small
git checkout

--filter 选项与远程协议的更新一起添加,可真正防止从服务器下载对象。

方法五:使用 git sparse-checkout

1
2
3
4
git clone --filter=blob:none --sparse https://github.com/git/git.git
cd git
git sparse-checkout init --cone
git sparse-checkout add t
  • --sparse 仅将 git 仓库的顶级目录文件检出到工作副本中。
  • git sparse-checkout add t 增量添加/检出 gitt 子文件夹。
  • git sparse-checkout init 进行一些准备工作以启用部分检出。
  • --filter=blob:none 通过仅下载必要的 git 对象来优化数据获取。
  • --cone 通过应用更严格的文件包含模式来提高性能。

方法六:使用脚本下载

以下是一个使用 curlawk 的脚本,用于下载 GitHub 目录中的所有文件:

1
curl -s https://api.github.com/repos/:user/:repo/contents/:path | awk '/download_url/ { gsub("\"|,", "", $2); system("curl -O " $2); }'

此脚本调用 GitHub REST API,通过 curl 获取目录内容的 JSON 对象,然后使用 awk 过滤出 download_url 行,去除引号和逗号,并使用另一个 curl 调用下载链接。

核心代码

使用 git-archive(不适用于 GitHub 仓库)

1
git archive --format tar --remote ssh://server.org/path/to/Git HEAD docs/usage > /tmp/usage_docs.tar

使用 git svn

1
git svn clone https://github.com/lodash/lodash/trunk/test

自定义下载函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
function download_from_git() {
local git_remote="$1"
local git_ref="$2"
local git_path="$3"
local target="$4"

temp_dir=$(mktemp -d temp-git-repo-XXXXXXXX)

if git archive --remote="$git_remote" "$git_ref" "$git_path" | tar -x -C "$temp_dir"; then
git_path_exists=$(ls -d "$temp_dir/$git_path" 2>/dev/null)
if [ -z "$git_path_exists" ]; then
echo "Error: The specified Git path does not exist in the repository."
return 1
fi

if [ -d "$temp_dir/$git_path" ]; then
mkdir -p "$target"
mv "$temp_dir/$git_path/"* "$target/"
else
mkdir -p "$(dirname "$target")"
mv "$temp_dir/$git_path" "$target"
fi
else
git clone --depth 1 --branch "$git_ref" --filter=blob:none "$git_remote" "$temp_dir"
cd "$temp_dir"

git restore --source "$git_ref" -- "$git_path"

cd - > /dev/null

git_path_exists=$(ls -d "$temp_dir/$git_path" 2>/dev/null)
if [ -z "$git_path_exists" ]; then
echo "Error: The specified Git path does not exist in the repository."
return 1
fi

if [ -d "$temp_dir/$git_path" ]; then
mkdir -p "$target"
mv "$temp_dir/$git_path/"* "$target/"
else
mkdir -p "$(dirname "$target")"
mv "$temp_dir/$git_path" "$target"
fi
fi

rm -rf "$temp_dir"
}

用法

1
download_from_git "https://github.com/rustwasm/wasm-pack.git" "master" "npm" "./node-modules/wasm-pack/"

最佳实践

  • 选择合适的工具:根据自己的需求和环境选择合适的下载方法。如果只需要偶尔下载,使用社区工具可能更方便;如果需要自动化下载,可考虑使用脚本或 API。
  • 处理大文件和大仓库:对于包含大文件的仓库,使用 git clone --filtergit sparse-checkout 可以避免下载不必要的文件,节省时间和存储空间。
  • 注意 API 限制:如果使用 GitHub API 进行下载,要注意 API 的速率限制,必要时提供令牌以避免限制。

常见问题

  • Subversion 支持已移除:自 2024 年 1 月 8 日起,GitHub 已移除对 Subversion 的支持,因此无法再使用 SVN 方法下载文件夹。
  • 工具需要 API 令牌:一些工具(如部分社区工具)在下载大量文件时可能需要提供 API 令牌,否则可能会受到速率限制。
  • 下载速度慢:对于大型仓库,下载可能会比较慢。可以尝试使用 git clone --filtergit sparse-checkout 等方法只下载必要的文件,以提高下载速度。

从GitHub仓库下载单个文件夹或目录
https://119291.xyz/posts/download-a-single-folder-or-directory-from-a-github-repository/
作者
ww
发布于
2025年5月23日
许可协议