如何仅克隆Git存储库的子目录?

2001

我有一个Git仓库,根目录下有两个子目录:

/finisht
/static

当这个项目在SVN上时,/finisht被检出到一个地方,而/static则被检出到另一个地方,如下所示:

svn co svn+ssh://admin@domain.example/home/admin/repos/finisht/static static

有没有使用Git的方法可以实现这个?


18
可能是 Checkout subdirectories in Git? 的重复问题。 - Joachim Breitner
2
对于一个2014年的用户,git clone最简单的命令是什么?我使用了这个简单的答案。如果有更简单的方法,请评论。 - Peter Krauss
1
对于那些尝试克隆存储库内容(而不是创建根文件夹)的人来说,这是一个非常简单的解决方案:https://dev59.com/zG025IYBdhLWcg3wFxua - Marc
2
@NickSergeant:自Git 2.19发布三周以来,这终于成为可能,可以在此答案中看到:https://dev59.com/QHRB5IYBdhLWcg3wgXhV#52269934 考虑现在接受它。注意:在Git 2.19中,仅实现了客户端支持,服务器端支持仍然缺失,因此仅在克隆本地存储库时才起作用。还要注意,大型Git主机(例如GitHub)实际上不使用Git服务器,而是使用自己的实现,因此即使支持出现在Git服务器上,也不意味着它会自动在Git主机上工作。(另一方面,他们可以更快地实现它。) - Jörg W Mittag
4
如果你想从 GitHub 存储库下载一个文件夹,https://download-directory.github.io/ 可能是个好选择。 - jemand771
显示剩余6条评论
31个回答

11

编写了一个脚本,用于从GitHub下载子目录。

用法:

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

13
知道了,这只是针对GitHub的事情。 - Sz.
10
看起来这是用于下载目录,而不是使用其所有元数据克隆资料库的一部分...对吗? - LarsH
14
你应该在这里包含你的代码,而不是其他地方。 - jww
urllib2.HTTPError: HTTP错误 403:超过速率限制 - diyism
要下载一个目录,请查看https://stackoverflow.com/a/50925766/12649675以获取更好的Python脚本。 - undefined

11
这将克隆一个特定的文件夹并删除与它无关的所有历史记录。
git clone --single-branch -b {branch} git@github.com:{user}/{repo}.git
git filter-branch --subdirectory-filter {path/to/folder} HEAD
git remote remove origin
git remote add origin git@github.com:{user}/{new-repo}.git
git push -u origin master

2
这里有一些需要注意的地方。你会看到一个警告:git-filter-branch 存在许多陷阱,可能会导致历史记录被篡改。然后,git-filter-branch 文档中有一个相当长的警告列表。请参考 git-filter-branch 文档 - Oyvind

10

对我来说可行 - (git版本2.35.1)

git init
git remote add origin <YourRepoUrl>
git config core.sparseCheckout true
git sparse-checkout set <YourSubfolderName>
git pull origin <YourBranchName>

看起来这是最快和最短的方法。 - damdafayton

10

这是我所做的事情

git init
git sparse-checkout init
git sparse-checkout set "YOUR_DIR_PATH"
git remote add origin https://github.com/AUTH/REPO.git
git pull --depth 1 origin <SHA1_or_BRANCH_NAME>

简单说明

  • sparse-checkout

  • git sparse-checkout init 很多文章会告诉你要设置 git sparse-checkout init --cone 如果加上 --cone 会获取到一些不需要的文件。

  • git sparse-checkout set "...".git\info\sparse-checkout 文件内容设置为 ...

    假设你不想使用该命令,可以打开 git\info\sparse-checkout 文件后进行编辑。


示例

假设我想要获取完整 repo 大小>10GB↑(包含 git)2个文件夹,如下总大小< 2MB

  1. chrome/common/extensions/api
  2. chrome/common/extensions/permissions
git init
git sparse-checkout init
// git sparse-checkout set "chrome/common/extensions/api/"
start .git\info\sparse-checkout    open the "sparse-checkut" file

/* .git\info\sparse-checkout  for example you can input the contents as below 
chrome/common/extensions/api/
!chrome/common/extensions/api/commands/      ! unwanted : https://www.git-scm.com/docs/git-sparse-checkout#_full_pattern_set
!chrome/common/extensions/api/devtools/
chrome/common/extensions/permissions/
*/

git remote add origin https://github.com/chromium/chromium.git
start .git\config

/* .git\config
[core]
    repositoryformatversion = 1
    filemode = false
    bare = false
    logallrefupdates = true
    symlinks = false
    ignorecase = true
[extensions]
    worktreeConfig = true
[remote "origin"]
    url = https://github.com/chromium/chromium.git
    fetch = +refs/heads/*:refs/remotes/Github/*
    partialclonefilter = blob:none  //  Add this line, This is important. Otherwise, your ".git" folder is still large (about 1GB)
*/
git pull --depth 1 origin 2d4a97f1ed2dd875557849b4281c599a7ffaba03
// or
// git pull --depth 1 origin master

  • partialclonefilter = blob:none

    我知道添加这行代码是因为我从git clone --filter=blob:none 命令中得知它会生成这行代码,所以我模仿了它。

Git 版本:git version 2.29.2.windows.3


这在Linux上给我错误提示:"Sparse checkout leaves no entry on working directory"git pull --depth 1 origin dev - Sudhir N

8

正在使用 Linux?只需访问易于使用且整洁的工作目录,而无需打扰计算机上的其他代码。尝试使用符号链接

git clone https://github.com:{user}/{repo}.git ~/my-project
ln -s ~/my-project/my-subfolder ~/Desktop/my-subfolder

测试

cd ~/Desktop/my-subfolder
git status

7

为了澄清一些很好的答案,许多答案中概述的步骤都假设您已经有了远程存储库。

给定:一个现有的Git存储库,例如git@github.com:some-user/full-repo.git,其中包含一个或多个您希望独立于其余存储库拉取的目录,例如名为app1 app2的目录。

假设您有一个如上所述的Git存储库...

那么: 您可以运行以下步骤,仅从该较大的存储库中拉取特定目录:

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

我曾误以为稀疏检出选项必须在原始存储库上设置,但实际上不是这样的:在从远程拉取之前,您可以定义要本地使用的目录。远程仓库不知道也不关心您只想跟踪存储库的一部分。
希望这个澄清能帮助其他人。

这有点晚了,但如果我需要app1内的所有内容而不是app1目录,我该怎么办? - Swapnil Shende
这似乎更像是一个表面问题,尽管看起来你似乎没有完全自由地“逃脱”原始repo的结构。也许你可以使用符号链接? - Everett
似乎仍需要下载整个存储库$ mkdir com.unity.render-pipelines.core $ cd com.unity.render-pipelines.core/ $ git init $ git remote add origin https://github.com/Oculus-VR/Unity-Graphics.git $ git config core.sparsecheckout true $ echo "com.unity.render-pipelines.core/" >> .git/info/sparse-checkout $ git pull origin 2021.2/oculus-appsw-particles文件夹大小约为7mb,但是...$ ... $ Receiving objects: 6% (24305/375290), 27.30 MiB | 121.00 KiB/s - Vlad

6

我为单个子目录稀疏检出编写了一个shell脚本

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

2
不错的脚本,唯一需要修复的是符号链接,应该是 ln -s ./.$localRepo/$subDir $localRepo 而不是 ln -s ./.$localRepo$subDir $localRepo - valentin_nasta

4
git init <repo>
cd <repo>
git remote add origin <url>
git config core.sparsecheckout true
echo "<path you want to clone>/*" >> .git/info/sparse-checkout
git pull --depth=1 origin <branch you want to fetch>

示例仅克隆此repo中的Jetsurvey文件夹

git init MyFolder
cd MyFolder 
git remote add origin git@github.com:android/compose-samples.git
git config core.sparsecheckout true
echo "Jetsurvey/*" >> .git/info/sparse-checkout
git pull --depth=1 origin main

3

@Chronial的答案已经不适用于最近的版本,但它提供了一个有用的脚本。

根据我收集的信息和我只想检出分支的子目录这一事实,我创建了以下shell函数。它获取提供的目录中分支最新版本的浅层副本。

function git_sparse_clone_branch() (
  rurl="$1" localdir="$2" branch="$3" && shift 3

  git clone "$rurl" --branch "$branch" --no-checkout "$localdir" --depth 1  # limit history
  cd "$localdir"

  # git sparse-checkout init --cone  # fetch only root file

  # Loops over remaining args
  for i; do
    git sparse-checkout set "$i"
  done

  git checkout "$branch"
)

因此,以下是使用示例:

git_sparse_clone_branch git@github.com:user/repo.git localpath branch-to-clone path1_to_fetch path2_to_fetch

在我的情况下,克隆版本只有23MB,而完整克隆版本为385MB。

使用git版本2.36.1测试。


3
这里有很多不错的回复,但我想补充一下,在Windows Server 2016上,使用目录名称周围的引号会导致失败。文件根本没有被下载。
与其这样做:
"mydir/myfolder"

我不得不使用

mydir/myfolder

此外,如果您只想下载所有子目录,请使用以下命令:

git sparse-checkout set *

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