简体中文 ▾ 主题 ▾ 最新版本 ▾ 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 对象进行“离线”传输。

它们既可用于创建仓库的增量备份和全量备份(参见“示例”中的“全量备份”示例),也可用于将一个仓库的引用状态转发到另一个仓库(参见第二个示例)。

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

离线包格式

Bundle 是带有标头(标明包内包含哪些引用)的 .pack 文件(参见 git-pack-objects[1])。

与打包归档格式本身一样,bundle 可以是自包含的,也可以使用排除项创建。请参阅下文的“对象依赖前置条件”部分。

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

使用修订版本排除项时没有创建“厚包(thick pack)”的选项,用户无需担心其中的区别。通过使用“瘦包”,使用排除项创建的 bundle 体积更小。这里仅将其底层是“瘦包”作为一个注记和对其他文档的引用。

更多详情请参见 gitformat-bundle[5],关于“瘦包”的讨论请参见 gitformat-pack[5]

选项

create [选项] <文件> <git-rev-list-参数>

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

verify <文件>

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

list-heads <文件>

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

unbundle <文件>

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

<git-rev-list-参数>

一组 git rev-parsegit rev-list 可接受的参数(且包含一个命名的引用,见下文“指定引用”),用于指定要传输的具体对象和引用。例如,master~10..master 会导致当前的 master 引用与其自第 10 代祖先提交以来添加的所有对象一起被打包。可以打包的引用和对象数量没有明确限制。

[<引用名>…​]

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

--progress

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

--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(可在没有共同历史的仓库中解包),也可以提供负修订版本以排除历史早期部分所需的对象。

git bundle create 提供诸如 new 之类的修订版本将创建一个 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-参数> 中使用 --branches --tags

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

示例

我们将讨论两种情况

  1. 对仓库进行全量备份

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

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

$ git bundle create backup.bundle --all

但请再次注意,这仅针对引用,即您将仅包含从这些引用可达的引用和提交。您将不会包含其他本地状态,例如索引内容、工作树、暂存(stash)、各仓库配置、钩子(hooks)等。

您稍后可以使用例如 git-clone[1] 来恢复该仓库

$ git clone backup.bundle <new directory>

下一个示例中,假设您想将历史从机器 A 上的仓库 R1 传输到机器 B 上的另一个仓库 R2。由于某些原因,A 和 B 之间不允许直接连接,但我们可以通过某种机制(光盘、电子邮件等)将数据从 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 中获取(fetch)和拉取(pull)。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 后,进行获取或拉取。

在原始仓库中进行更多工作后,您可以创建一个增量 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 就像一个它从中获取或拉取的常规仓库。例如,您可以在获取时映射引用

$ git fetch mybundle master:localRef

您也可以查看它提供的引用

$ git ls-remote mybundle

讨论

对仓库进行全量备份的一种简陋方法是使用类似于 cp -r <仓库> <目的地> 的操作。不建议这样做,因为在复制操作期间仓库可能会被写入。反过来,<目的地> 的某些文件可能会损坏。

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

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

文件格式

GIT

Git[1] 套件的一部分