是否可以仅克隆 git 项目的一部分?

是否可以仅克隆 git 项目的一部分?

我找到了 slackbuilds 的集合,其中一些我需要的在 GitHub 上。 https://github.com/PhantomX/slackbuilds/ 我不想得到所有的 git。

git clone https://github.com/PhantomX/slackbuilds.git

但只能得到一个 slackbuild,对于这个

这个怎么做?是否可以?

答案1

您最终将下载整个历史记录,因此我看不到它有多大好处,但您可以使用“稀疏”结帐来结帐特定部分。引用这个堆栈溢出帖子:

稀疏化的步骤克隆如下面所述:

mkdir <repo>
cd <repo>
git init
git remote add -f origin <url>

我要在这里打断一下。由于我引用了另一篇文章,因此我不想编辑引用的部分,但是不是-f与 一起使用git remote add。它将进行一次提取,这将提取整个历史记录。只需添加遥控器而无需获取:

git remote add origin <url>

然后像后面描述的那样进行浅层获取。

这将使用您的遥控器创建一个空存储库,并获取所有对象,但不会将它们签出。然后做:

git config core.sparseCheckout true

现在您需要定义您想要实际签出哪些文件/文件夹。这是通过将它们列出来完成的.git/info/sparse-checkout,例如:

echo "some/dir/" >> .git/info/sparse-checkout
echo "another/sub/tree" >> .git/info/sparse-checkout

[...]

您可能想看看扩展教程你可能应该阅读官方的稀疏结帐的文档

你可能最好使用浅克隆。而不是普通的git pull,请尝试:

git pull --depth=1 origin master

我最近有机会再次测试这个,试图只得到Ubuntu Mono Powerline 字体。上述步骤最终下载了大约 11 MB,其中 Ubuntu 字体本身约为 900 KB:

% git pull --depth=1 origin master
remote: Enumerating objects: 310, done.
remote: Counting objects: 100% (310/310), done.
remote: Compressing objects: 100% (236/236), done.
remote: Total 310 (delta 75), reused 260 (delta 71), pack-reused 0
Receiving objects: 100% (310/310), 10.40 MiB | 3.25 MiB/s, done.
Resolving deltas: 100% (75/75), done.
From https://github.com/powerline/fonts
 * branch            master     -> FETCH_HEAD
 * [new branch]      master     -> origin/master
% du -hxd1 .
11M     ./.git
824K    ./UbuntuMono
12M     .

正常的clone大约需要 20 MB。有一些积蓄,但还不够。

使用--filterCiro Santilli 答案中的 + 结账方法确实减少了大小,但正如那里提到的,逐一下载每个 blob,这很慢:

% git fetch --depth=1 --filter=blob:none
remote: Enumerating objects: 52, done.
remote: Counting objects: 100% (52/52), done.
remote: Compressing objects: 100% (49/49), done.
remote: Total 52 (delta 1), reused 35 (delta 1), pack-reused 0
Receiving objects: 100% (52/52), 14.55 KiB | 1.32 MiB/s, done.
Resolving deltas: 100% (1/1), done.
From https://github.com/powerline/fonts
 * [new branch]      master     -> origin/master
 * [new branch]      terminus   -> origin/terminus
% git checkout origin/master -- UbuntuMono
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (1/1), 1.98 KiB | 1.98 MiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 1 (delta 0), pack-reused 0
Receiving objects: 100% (1/1), 581 bytes | 581.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 1 (delta 0), pack-reused 0
Receiving objects: 100% (1/1), 121.43 KiB | 609.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 1 (delta 0), pack-reused 0
Receiving objects: 100% (1/1), 100.66 KiB | 512.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 1 (delta 0), pack-reused 0
Receiving objects: 100% (1/1), 107.62 KiB | 583.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 1 (delta 0), pack-reused 0
Receiving objects: 100% (1/1), 112.15 KiB | 791.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 1 (delta 0), pack-reused 0
Receiving objects: 100% (1/1), 454 bytes | 454.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 1 (delta 0), pack-reused 0
Receiving objects: 100% (1/1), 468 bytes | 468.00 KiB/s, done.
% du -hxd1 .
692K    ./.git
824K    ./UbuntuMono
1.5M    .

TL;DR:使用全部--filter、稀疏检出和浅克隆来减少总下载量,或者如果您不关心总下载量并且只想要一个目录(无论如何获得),则仅使用稀疏检出 + 浅克隆。

答案2

git clone --filter+git sparse-checkout仅下载所需的文件

例如,仅克隆small/此测试存储库中子目录中的文件:https://github.com/cirosantilli/test-git-partial-clone-big-small-no-bigtree

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

您还可以选择多个目录进行下载:

git sparse-checkout set --no-cone small small2

然而,此方法不适用于单个文件,但这是另一种方法:https://stackoverflow.com/questions/2466735/how-to-sparsely-checkout-only-one-single-file-from-a-git-repository/52270527#52270527

在这个测试中,克隆基本上是瞬时的,我们可以确认克隆的存储库非常小,如我们所愿:

du --apparent-size -hs * .* | sort -hs

给予:

2.0K    small
226K    .git

该测试存储库包含:

  • big/包含 10 个 10MB 文件的子目录
  • 10x 10MB 文件0, 1, ...9在顶层(这是因为之前的某些尝试会下载顶层文件)
  • asmall/small2/子目录,包含 1000 个文件,每个文件大小为 1 字节

所有内容都是伪随机的,因此不可压缩,因此我们可以轻松注意到是否下载了任何大文件,例如ncdu

因此,如果您下载了不需要的任何内容,您将获得 100 MB 的额外空间,这将是非常明显的。

在上面,git clone下载单个对象,大概是提交:

Cloning into 'test-git-partial-clone-big-small'...
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 1 (delta 0), pack-reused 0
Receiving objects: 100% (1/1), done.

然后最终结帐下载我们请求的文件:

remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), 10.19 KiB | 2.04 MiB/s, done.
remote: Enumerating objects: 253, done.
remote: Counting objects: 100% (253/253), done.
Receiving objects: 100% (253/253), 2.50 KiB | 2.50 MiB/s, done.
remote: Total 253 (delta 0), reused 253 (delta 0), pack-reused 0
Your branch is up to date with 'origin/master'.

于 2023 年 1 月在 git 2.37.2、Ubuntu 22.10 上进行了测试。

TODO 还可以防止下载不需要的树对象

以上方法全部下载Git 树对象(即目录列表,但不是实际文件内容)。我们可以通过运行来确认:

git ls-files

并看到它包含大文件目录,例如:

big/0

在大多数项目中,这不会成为问题,但我的完美主义者希望避免它们。

我还在目录下创建了一个非常极端的存储库,其中包含一些非常大的树对象(100 MB)big_treehttps://github.com/cirosantilli/test-git-partial-clone-big-small

small/如果有人找到了仅从中克隆目录的方法,请告诉我!

关于命令

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

不幸的是,这sparse-checkout部分也是需要的。您还可以只下载某些更容易理解的文件:

git clone --depth 1  --filter=blob:none  --no-checkout \
  https://github.com/cirosantilli/test-git-partial-clone-big-small
cd test-git-partial-clone-big-small
git checkout master -- d1

但由于某种原因该方法一个接一个地下载文件非常慢,除非目录中的文件很少,否则它无法使用。

另一个不太详细但失败的尝试是:

git clone --depth 1 --filter=blob:none --sparse \
  https://github.com/cirosantilli/test-git-partial-clone-big-small
cd test-git-partial-clone-big-small
git sparse-checkout set small

但这会下载顶级目录中的所有文件:https://stackoverflow.com/questions/75311408/how-to-prevent-git-clone-filter-blobnone-sparse-from-downloading-files-on-t

梦想:任何目录都可以拥有 Web 界面元数据

这个功能可能会彻底改变 Git。

想象一下拥有您企业的所有代码库在单个单一存储库中没有丑陋的第三方工具,例如repo

想象将巨大的 blob 直接存储在存储库中,无需任何丑陋的第三方扩展

想象一下如果 GitHub 允许的话每个文件/目录元数据例如星星和权限,因此您可以将所有个人内容存储在一个存储库下。

想象一下如果子模块的处理方式与常规目录完全相同:只需请求一个树 SHA 和一个类似 DNS 的机制解析您的请求,首先看你的当地的~/.git,然后首先到更近的服务器(您企业的镜像/缓存)并最终到达 GitHub。

我有一个梦想。

测试锥 monorepo 理念

这是没有子模块的 monorepo 维护的可能理念。

我们希望避免使用子模块,因为每次进行具有子模块和非子模块组件的更改时都必须提交到两个单独的存储库,这很烦人。

每个带有 Makefile 或类似文件的目录都应该自行构建和测试。

此类目录可以取决于:

  • 其下的每个文件和子目录都直接为其最新版本
  • 外部目录只能在指定版本上依赖

在 git 开始原生支持此功能(即只能跟踪子目录的子模块)之前,我们可以使用 git 跟踪文件中的一些元数据来支持此功能:

monorepo.json

{
    "path": "some/useful/lib",
    "sha": 12341234123412341234,
}

其中指sha的是整个存储库的常用 SHA。然后我们需要脚本来检出此类目录,例如在 gitignoredmonorepo文件夹下:

monorepo/som/useful/lib

每当您更改文件时,您都必须沿着树向上测试所有具有 Makefile 的目录。这是因为目录可能依赖于最新版本的子目录,因此您总是可能会破坏上面的某些内容。

有关的:

答案3

尝试这个:

svn export https://github.com/PhantomX/slackbuilds/trunk/${directory}

答案4

由于上述原因,我终于成功了。我直接编辑文件,由于不小心包含引号而出现错误。您的 .git/info/sparse-checkout 文件应仅包含目录,不包含引号。这是一个例子:这个巨大的项目:https://github.com/SharePoint/sp-dev-fx-webparts,我只想要示例目录中的react-script-editor。 https://github.com/SharePoint/sp-dev-fx-webparts/tree/master/samples/react-script-editor

我按照上面的说明操作,当我的 .git/info/sparse-checkout 文件中只有这个时,它就开始工作了

样本/反应脚本编辑器

相关内容