简体中文 ▾ 主题 ▾ 最新版本 ▾ git-bundle 最近更新于 2.48.0

名称

git-bundle - 通过存档移动对象和引用

概要

git bundle create [-q | --quiet | --progress]
		    [--version=<version>] <file> <git-rev-list-args>
git bundle verify [-q | --quiet] <file>
git bundle list-heads <file> [<refname>…​]
git bundle unbundle [--progress] <file> [<refname>…​]

描述

创建、解包和操作“bundle”文件。Bundle 文件用于“离线”传输 Git 对象,而无需网络连接的另一端有活动的“服务器”。

它们可以用于创建仓库的增量和完整备份(参见“EXAMPLES”中的“完整备份”示例),以及将一个仓库中的引用状态传输到另一个仓库(参见第二个示例)。

通过 ssh://https:// 等协议获取或以其他方式“读取”的 Git 命令也可以对 bundle 文件进行操作。可以从 bundle git-clone[1] 一个新仓库,使用 git-fetch[1] 从中获取数据,并使用 git-ls-remote[1] 列出其中包含的引用。没有相应的“写入”支持,即不支持将 git push 到 bundle 中。

BUNDLE 格式

Bundle 文件是 .pack 文件(参见 git-pack-objects[1]),带有指示 bundle 中包含哪些引用的头部信息。

与打包存档格式本身一样,bundle 可以是自包含的,也可以是使用排除项创建的。参见下面的“OBJECT PREREQUISITES”部分。

使用修订排除项创建的 bundle 是“thin pack”(稀疏包),通过 git-pack-objects[1]--thin 选项创建,并通过 git-index-pack[1]--fix-thin 选项解包。

使用修订排除项时,没有创建“thick pack”(厚包)的选项,用户也无需关注其差异。通过使用“thin pack”,使用排除项创建的 bundle 文件尺寸更小。此处仅将它们在底层是“thin”的这一事实作为一种趣事和对其他文档的引用加以说明。

有关更多详细信息,请参见 gitformat-bundle[5],有关“thin pack”的讨论,请参见 gitformat-pack[5]

选项

create [options] <file> <git-rev-list-args>

用于创建名为 file 的 bundle。这需要 <git-rev-list-args> 参数来定义 bundle 内容。options 包含 git bundle create 子命令特有的选项。如果 file-,则 bundle 将写入标准输出。

verify <file>

用于检查 bundle 文件是否有效,以及是否能干净地应用于当前仓库。这包括对 bundle 格式本身的检查,以及检查先决条件提交是否存在并完全链接到当前仓库中。然后,git bundle 会打印出缺失提交的列表(如果有)。最后,会打印有关其他功能(例如“对象过滤器”)的信息。有关更多信息,请参见 gitformat-bundle[5] 中的“Capabilities”。成功时退出代码为零,如果 bundle 文件无效,则为非零。如果 file-,则 bundle 从标准输入读取。

list-heads <file>

列出 bundle 中定义的引用。如果后面跟着一个引用列表,则只打印与给定引用匹配的引用。如果 file-,则 bundle 从标准输入读取。

unbundle <file>

将 bundle 中的对象传递给 git index-pack 以存储到仓库中,然后打印所有定义引用的名称。如果给定一个引用列表,则只打印与列表中匹配的引用。此命令实际上是底层命令(plumbing),旨在仅由 git fetch 调用。如果 file-,则 bundle 从标准输入读取。

<git-rev-list-args>

一个参数列表,可被 git rev-parsegit rev-list 接受(并包含一个命名引用,参见下面的“SPECIFYING REFERENCES”),用于指定要传输的特定对象和引用。例如,master~10..master 会将当前 master 引用及其自其第 10 个祖先提交以来添加的所有对象打包。对可打包的引用和对象数量没有明确限制。

[<refname>…​]

用于限制报告为可用引用的列表。这主要用于 git fetch,它期望只接收请求的引用,而不一定是包中的所有内容(在这种情况下,git bundle 的行为类似于 git fetch-pack)。

--progress

默认情况下,当标准错误流连接到终端时,会报告进度状态,除非指定了 -q。此标志强制报告进度状态,即使标准错误流未定向到终端。

--version=<version>

指定 bundle 版本。版本 2 是较旧的格式,只能与 SHA-1 仓库一起使用;较新的版本 3 包含允许扩展的功能。默认是支持的最旧格式,基于正在使用的哈希算法。

-q
--quiet

此标志使命令不在标准错误流上报告其进度。

指定引用

修订版必须附带引用名称才能打包到 bundle 中。或者可以使用 --all 来打包所有引用。

可以打包多个引用,也可以指定多组先决条件对象。打包的对象是不包含在先决条件集合中的那些。

git bundle create 命令使用与 git rev-parse --abbrev-ref=loose 相同的规则为您解析引用名称。每个先决条件都可以显式指定(例如 ^master~10),或隐式指定(例如 master~10..master, --since=10.days.ago master)。

所有这些简单情况都可行(假设我们有“master”和“next”分支)

$ git bundle create master.bundle master
$ echo master | git bundle create master.bundle --stdin
$ git bundle create master-and-next.bundle master next
$ (echo master; echo next) | git bundle create master-and-next.bundle --stdin

这些也一样(以及相同的但省略了 --stdin 的示例)

$ git bundle create recent-master.bundle master~10..master
$ git bundle create recent-updates.bundle master~10..master next~5..next

无法解析为引用的修订名称或范围的右侧不被接受

$ git bundle create HEAD.bundle $(git rev-parse HEAD)
fatal: Refusing to create empty bundle.
$ git bundle create master-yesterday.bundle master~10..master~5
fatal: Refusing to create empty bundle.

对象先决条件

创建 bundle 时,可以创建一个自包含的 bundle,它可以在没有共同历史的仓库中解包,也可以提供负修订版以排除历史早期部分所需的对象。

new 等修订版本提供给 git bundle create 将创建一个 bundle 文件,其中包含从 new 修订版本可访问的所有对象。该 bundle 可以在任何仓库中解包,以获取通往 new 修订版本的完整历史记录。

$ git bundle create full.bundle new

诸如 old..new 之类的修订范围将生成一个 bundle 文件,该文件将要求存在修订版 old(以及从中可访问的任何对象)才能“解包”该 bundle。

$ git bundle create full.bundle old..new

不带任何先决条件的自包含 bundle 可以解压到任何地方,即使是空仓库,也可以从中克隆(即 new,但不是 old..new)。

谨慎行事是正确的,这会导致 bundle 文件包含目标中已有的对象,因为这些对象在目标解包时会被忽略。

如果您想提供与直接从源仓库克隆时相同的引用集,请为 <git-rev-list-args> 使用 --branches --tags

git bundle verify 命令可用于检查您的接收仓库是否具有 bundle 所需的先决条件提交。

示例

我们将讨论两种情况

  1. 对仓库进行完整备份

  2. 当两台机器没有直接连接时,将仓库的历史传输到另一台机器

首先,我们考虑仓库的完整备份。以下命令将对仓库进行完整备份,即所有引用都包含在 bundle 中。

$ git bundle create backup.bundle --all

但请再次注意,这仅适用于引用,即您将只包含引用及其可达的提交。您将不包含其他本地状态,例如索引内容、工作树、暂存区、每个仓库的配置、钩子等。

您以后可以通过例如 git-clone[1] 恢复该仓库。

$ git clone backup.bundle <new directory>

对于下一个示例,假设您想将机器 A 上的仓库 R1 的历史传输到机器 B 上的另一个仓库 R2。由于某种原因,A 和 B 之间不允许直接连接,但我们可以通过某种机制(CD、电子邮件等)将数据从 A 移动到 B。我们想用 R1 中 master 分支上的开发成果更新 R2。

要启动此过程,您可以首先创建一个不带任何先决条件的 bundle。您可以使用标签来记住您上次处理到哪个提交,以便以后通过增量 bundle 轻松更新另一个仓库。

machineA$ cd R1
machineA$ git bundle create file.bundle master
machineA$ git tag -f lastR2bundle master

然后将 file.bundle 传输到目标机器 B。因为此 bundle 不需要任何现有对象才能提取,所以您可以通过从中克隆来在机器 B 上创建一个新仓库。

machineB$ git clone -b master /home/me/tmp/file.bundle R2

这将在生成的仓库中定义一个名为“origin”的远程,允许您从 bundle 中获取和拉取数据。R2 中的 $GIT_DIR/config 文件将有如下条目:

[remote "origin"]
    url = /home/me/tmp/file.bundle
    fetch = refs/heads/*:refs/remotes/origin/*

要更新生成的 mine.git 仓库,您可以在用增量更新替换存储在 /home/me/tmp/file.bundle 的 bundle 后,进行 fetch 或 pull 操作。

在原始仓库中进一步工作后,您可以创建一个增量 bundle 来更新另一个仓库。

machineA$ cd R1
machineA$ git bundle create file.bundle lastR2bundle..master
machineA$ git tag -f lastR2bundle master

然后将 bundle 传输到另一台机器以替换 /home/me/tmp/file.bundle,并从中拉取。

machineB$ cd R2
machineB$ git pull

如果您知道目标接收仓库应该拥有必要对象的提交,您可以使用该知识来指定先决条件,从而设置一个截止点以限制生成的 bundle 中包含的修订版和对象。前面的示例使用 lastR2bundle 标签来实现此目的,但您可以使用您会提供给 git-log[1] 命令的任何其他选项。以下是更多示例:

您可以使用两者都存在的标签

$ git bundle create mybundle v1.0.0..master

您可以使用基于时间的先决条件

$ git bundle create mybundle --since=10.days master

您可以使用提交的数量

$ git bundle create mybundle -10 master

您可以运行 git-bundle verify 来查看是否可以从带有先决条件创建的 bundle 中提取数据

$ git bundle verify mybundle

这将列出您必须拥有的提交才能从 bundle 中提取,如果您没有这些提交,则会报错。

从接收仓库的角度来看,bundle 就像一个常规仓库,它可以从中 fetch 或 pull。例如,您可以在 fetch 时映射引用:

$ git fetch mybundle master:localRef

您也可以查看它提供了哪些引用:

$ git ls-remote mybundle

讨论

对仓库进行完整备份的一种简单方法是使用 cp -r <repo> <destination>。不建议这样做,因为在复制操作期间可能会对仓库进行写入。反过来,<destination> 处的一些文件可能会损坏。

这就是为什么建议使用 Git 工具进行仓库备份,无论是使用此命令还是例如 git-clone[1]。但请记住,这些工具无法帮助您备份除引用和提交之外的状态。换句话说,它们无法帮助您备份索引内容、工作树、暂存区、每个仓库的配置、钩子等。

另请参见 gitfaq[7] 的“TRANSFERS”部分,了解与跨系统文件同步相关的问题讨论。

文件格式

GIT

Git[1] 套件的一部分

scroll-to-top