不需要克隆即可打包git存储库

6
我该如何打包一个git项目而不需要每次都克隆它?目前我总是执行以下命令。
git clone --mirror http://git_project
cd git_project
git bundle create '../git_project.lock' --all
cd ..
rm git_project -Force -Recurse

我希望能用一条命令完成这件事,例如:
git bundle create '../git_project.lock' --all --repository http://git_project

1
没有办法 - git bundle 只能用于本地仓库。为什么每次都要克隆项目?只需克隆一次,然后使用 git fetch/pull 进行更新即可。使用裸仓库可以改进。 - phd
@phd:我将把这些捆绑文件作为备份放在另一台机器上,就像这个答案中所述:https://dev59.com/sG035IYBdhLWcg3wK80m - H. Pauwelyn
然后在另一台机器上运行 git bundle - phd
@phd:它在云端...我们无法访问那台机器... - H. Pauwelyn
1
那么本地克隆是您唯一的选择。但是您不需要每次都克隆。只需克隆一次,保留克隆版本,然后使用git fetch/pull更新它。像往常一样从克隆版本创建备份包。 - phd
@phd:但是如果您不删除存储库,则“git bundle create”根本没有意义。我会考虑什么是最好的事情。感谢信息@phd :) - H. Pauwelyn
1个回答

1
我将在另一台机器上备份这些捆绑文件。
自从我2011年的回答(11年前),现在你有了像GitHub ActionsGitLab CI这样的远程管道。
这些远程Git存储库托管服务上的自动化管道可以为您创建一个捆绑文件并将其保存到服务器/备份中。
这就是今天。

明天,您将能够访问一个专用于"git bundle"的服务器,通过一个bundle URI进行访问。

随着Git 2.38(2022年第三季度)的发布,"bundle URI"设计得到了文档化。

请查看提交记录d06ed85提交记录2da14fa(2022年8月9日),作者为Derrick Stolee(derrickstolee
(由Junio C Hamano -- gitster --提交记录0d133a3中合并,2022年8月18日)

文档:文档包URI标准

签署者:Derrick Stolee

通过一个雄心勃勃的设计文档,将捆绑URI的想法引入Git代码库。
该文档包括完整的设计,旨在以其完全实现的形式包含该功能。
这将需要多个步骤,详见“实施计划”部分。

通过现在提交此文档,可以用来激励必要的更改以达到这些最终目标。
随着发现新信息,设计仍然可以被修改。

technical/bundle-uri现在已包含在其手册页面中:

Bundle URIs

Git bundles是存储Pack文件以及一些额外元数据(包括一组引用和可能为空的必需提交集)的文件。有关更多信息,请参见 git bundle 和link:bundle-format.txt[捆绑格式]。

Bundle URI是Git可以下载一个或多个bundle的位置,以便在从远程获取其余对象之前预先引导对象数据库。

一个目标是加速用户克隆和提取,减轻原始服务器与较差网络连接用户的负载。另一个好处是允许重度用户,例如CI构建农场,使用本地资源来处理大部分Git数据,从而减少对原始服务器的负载。

为了启用Bundle URI功能,用户可以使用命令行选项指定Bundle URI,或者源服务器可以通过协议v2功能广告一个或多个URI。

另请参阅

bundle-uri:添加示例绑定组织

签署者:Derrick Stolee

添加一个部分详细说明如何工作的包提供商,包括使用Git服务器广告来多个地理分布式服务器。这个组织基于GVFS Cache服务器,它们已经成功使用类似的思想为非常大的代码库提供快速对象访问和减少服务器负载。

technical/bundle-uri现在在其手册页面中包含:

示例 Bundle 提供者组织

这个示例组织是 GVFS 缓存服务器(请参见本文档末尾的部分)使用的简化模型,对于非常大的仓库克隆和提取操作,它们已经被证明可以加速,但需要在 Git 之外使用额外的软件。

Bundle 提供者在多个地理位置部署服务器。
每个服务器管理自己的 bundle 集合。

服务器可以跟踪多个 Git 仓库,但根据模式为每个仓库提供一个 bundle 列表。

例如,在镜像位于 https://<domain>/<org>/<repo> 的仓库时,bundle 服务器可以将其 bundle 列表可用于 https://<server-url>/<domain>/<org>/<repo>.
原始 Git 服务器可以在“任意”模式下列出所有这些服务器:

[bundle]
version = 1
mode = any

[bundle "eastus"]
uri = https://eastus.example.com/<domain>/<org>/<repo>

[bundle "europe"]
uri = https://europe.example.com/<domain>/<org>/<repo>

[bundle "apac"]
uri = https://apac.example.com/<domain>/<org>/<repo>

这个“列表的列表”是静态的,只有在添加或删除 bundle 服务器时才会更改。

bundle 服务器定期运行 bundle 列表的更新任务,例如每天一次。
在此任务期间,服务器从原始服务器获取最新内容,并生成一个包含从最新原始引用可达但不包含在先前计算的 bundle 中的对象的 bundle。
将此 bundle 添加到列表中,确保 creationToken 严格大于先前的最大值 creationToken

这里提供了一个示例 bundle 列表,尽管它只有两个每日 bundle,而不是完整的 30 个:

[bundle]
version = 1
mode = all
heuristic = creationToken

[bundle "2022-02-13-1644770820-daily"]
uri = https://eastus.example.com/<domain>/<org>/<repo>/2022-02-09-1644770820-daily.bundle
creationToken = 1644770820

[bundle "2022-02-09-1644442601-daily"]
uri = https://eastus.example.com/<domain>/<org>/<repo>/2022-02-09-1644442601-daily.bundle
creationToken = 1644442601

[bundle "2022-02-02-1643842562"]
uri = https://eastus.example.com/<domain>/<org>/<repo>/2022-02-02-1643842562.bundle
creationToken = 1643842562

这个数据组织的目的有两个主要目标。

  • 首先,仓库的初始克隆可以通过从更近的源下载预计算的对象数据来加快。

  • 其次,git fetch 命令可以更快,特别是如果客户端已经有几天没有进行提取操作。但是,如果客户端 30 天内没有进行提取操作,则 bundle 列表组织将导致重新下载大量对象数据。


这是已经实现的(仍使用Git 2.38(2022年第三季度)):"git clone --bundle-uri"(man)

请参见 commit 65da938(2022年8月23日),commit e21e663commit 59c1752commit 5556891commit 53a5089commit b5624a4(2022年8月9日),作者为 Derrick Stolee (derrickstolee)
(由 Junio C Hamano -- gitster -- 合并于 commit 68ef042,2022年9月1日)

clone: 添加 --bundle-uri 选项

经过审核:Josh Steadmon
签名作者:Derrick Stolee

克隆远程存储库是Git中最昂贵的操作之一。服务器可能会花费大量CPU时间为客户端请求生成pack文件。数据量可能会长时间阻塞网络,而Git协议不可恢复。对于网络连接差或距离源服务器较远的用户来说,这可能特别痛苦。
在“git clone(man)中添加一个新的“--bundle-uri”选项,以从捆绑包引导克隆。如果用户知道捆绑包服务器,则可以告诉Git在从源服务器获取剩余对象之前使用这些捆绑包引导新存储库。

git clone现在在其man页面中包含以下内容:

--bundle-uri=<uri>

从远程获取之前,从给定的<uri>获取一个捆绑包并将数据解包到本地存储库中。

捆绑包中的引用将存储在隐藏的refs/bundle/*命名空间下。

此选项与--depth--shallow-since--shallow-exclude不兼容。


Git 2.39(2022年第4季度)定义了一个“bundle list”的逻辑元素,它是一种数据结构,用于将它们存储在内核中,传输格式以及解析它们的代码。

请查看 commit 8628a84, commit 70334fc, commit 89bd7fe, commit c23f592, commit c96060b, commit 20c1e2a, commit 738e524, commit bff03c4, commit 0634f71, commit 23b6d00 (2022年10月12日) 由 Derrick Stolee (derrickstolee) 提交。
请查看 commit d796ced, commit 9424e37 (2022年10月12日) 由 Ævar Arnfjörð Bjarmason (avar) 提交。
请查看 commit f677f62 (2022年8月24日) 由 Junio C Hamano (gitster) 提交。
(已合并于 commit d32dd8a,作者为 Taylor Blau -- ttaylorr --,2022年10月30日)

bundle-uri:获取捆绑包列表

签名作者:Derrick Stolee

当给定的捆绑URI内容不被视为捆绑时(基于检查初始内容),Git当前会放弃并忽略该内容。独立的捆绑提供者可能希望将捆绑内容拆分成多个捆绑,但仍然从单个URI中提供它们。
教导Git尝试将捆绑URI内容解析为Git配置文件,提供捆绑列表的键值对。然后,Git查看列表的模式,以查看任何单个捆绑是否足够或是否需要所有捆绑。所选URI处的内容将被下载,并再次进行检查,创建递归过程。
为了防止格式错误或恶意内容的递归,现在将递归深度限制为合理的四个。如果必要,这可以在未来转换为配置值。四的值是预期有用的两倍(捆绑列表不太可能指向更多的捆绑列表)。
为了测试这种情况,创建一个有趣的捆绑拓扑结构,其中三个增量捆绑建立在单个完整捆绑之上。通过使用合并提交,中间的两个捆绑“独立”,因为它们不需要彼此才能解开自己的捆绑。它们只需要基础捆绑。包含合并提交的捆绑需要中间的两个捆绑。这在解开捆绑时会导致一些有趣的决策,特别是当我们后来实现启发式算法以促进下载捆绑直到满足先决提交为止。

Git 2.40(2023年第一季度)继续实现捆绑URI(第4部分)。

查看 提交 876094a, 提交 12b0a14, 提交 ebc3947, 提交 9ea5796, 提交 738dc7d, 提交 1b759e0 (2022年12月22日) 由 Derrick Stolee (derrickstolee) 提交。
查看 提交 70b9c10, 提交 7cce907, 提交 0cfde74, 提交 8f788eb, 提交 8b8d9a2 (2022年12月22日) 由 Ævar Arnfjörð Bjarmason (avar) 提交。
(由 Junio C Hamano -- gitster -- 合并于 提交 0903d8b, 2023年1月2日)

bundle-uri client:添加布尔型设置transfer.bundleURI

合著者:Derrick Stolee
签署者:Ævar Arnfjörð Bjarmason
签署者:Derrick Stolee

尚未推出的bundle-uri客户端支持将始终回退到完整克隆,但我们仍希望能够完全忽略服务器的bundle-uri广告。

新的transfer.bundleURI配置选项默认为“false”,但用户可以将其设置为“true”以启用使用协议v2从源Git服务器检查bundle URI。

git config现在包括在其man页面中:

transfer.bundleURI

当设置为true时,本地的git clone命令将从远程服务器请求bundle信息(如果有广告),并通过Git协议在继续克隆之前下载bundles。
默认值为false

bundle-uri:从配置中提供bundle.* keys

由Derrick Stolee签署

通过从本地Git配置中填充key=value数据包行来实现“bundle-uri”协议v2功能。
bundles列表是从以“bundle.”开头的键提供的。

bundle-uri:在捆绑列表中允许相对URL

签署者:Derrick Stolee

捆绑提供者可能希望将数据分布在多个CDN上。
这可能需要更改基本URI,一直到域名为止。
如果所有捆绑都需要其'uri'值中的绝对URI,那么每次推送到CDN都需要修改目录以匹配预期的域和其中的确切位置。

允许捆绑列表指定捆绑的相对URI

此URI基于客户端接收捆绑列表的位置。
对于在'bundle-uri'协议v2命令中提供的列表,Git远程URI是基本URI。
否则,捆绑列表是从未使用Git协议的HTTP URI提供的,并且该URI是基本URI。
这使得捆绑数据更容易分发。


在 Git 2.40 (2023年第一季度) 中,bundle-URI 子系统添加了创建令牌启发式的支持,以帮助增量获取。

请查看 提交 026df9e, 提交 c429bed, 提交 7f0cc04, 提交 0524ad3, 提交 4074d3c, 提交 7903efb, 提交 512fccf, 提交 c93c3d2, 提交 7bc73e7, 提交 d9fd674, 提交 e72171f (2023年1月31日) 由 Derrick Stolee (derrickstolee) 提交。
(由 Junio C Hamano -- gitster -- 合并于 提交 4f59836, 2023年2月15日)

克隆:如适用,请设置fetch.bundleURI

签名作者:Derrick Stolee

Bundle提供者可以以旨在改善增量获取而不仅仅是初始克隆的方式组织其Bundle列表。但是,他们需要声明已经考虑到了这一点,否则客户端将不会期望通过下载初始克隆之后的Bundle来节省时间。这是通过指定bundle.heuristic值来实现的。有两种类型的Bundle列表:静态URI上的列表和通过协议v2从Git远程广告的列表。新的fetch.bundleURI配置值适用于未通过协议v2广告的静态Bundle URI。如果用户通过`git clone --bundle-uri` 指定了静态URI,则Git可以将此配置设置为提醒将来的git fetch操作在连接到远程之前检查bundle列表。对于通过协议v2提供的列表,我们将使用不同的方法,并通过创建remote..*类型的配置键来创建远程本身的属性。这种更改尚未实施。稍后的更改将更新git fetch以使用此选项。

git config现在包含在其man页面中:

fetch.bundleURI

此值存储从捆绑包URI下载Git对象数据的URI,然后从原始Git服务器执行增量获取。

这类似于--bundle-uri选项在git clone中的行为。
如果提供的捆绑包URI包含为增量获取组织的捆绑包列表,则git clone --bundle-uri将设置fetch.bundleURI值。


"git fetch --all"(man) 不必一遍又一遍地下载和处理相同的 bundleURI,这个问题已经在 Git 2.41(2023 年第二季度)中得到了修正。

请查看 提交 25bccb4(2023年3月31日),作者为Derrick Stolee(derrickstolee
(由Junio C Hamano -- gitster --提交89833fc中合并,于2023年4月6日)

fetch:即使使用--all也只需下载一次捆绑包

签署者:Derrick Stolee

当设置了fetch.bundleURI时,'git fetch'(man)会从给定的bundle URI下载bundles,然后再从指定的远程仓库中获取。
但是,当使用非文件远程仓库时,'git fetch --all'将启动'git fetch'子进程,然后读取fetch.bundleURI并再次获取bundle列表。
我们不希望在这些多次运行期间bundle列表有新信息,因此请在子进程参数中取消设置fetch.bundleURI以避免这些额外的调用。

请注意跳过空bundle字符串的获取。
从空列表中获取bundles会导致一些有趣的测试失败。


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