簡體中文 ▾ 主題 ▾ 最新版本 ▾ 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 檔案。可以 git-clone[1] 一個新的倉庫,可以透過 git-fetch[1] 從 bundle 獲取,並使用 git-ls-remote[1] 列出其中包含的引用。沒有相應的“寫入”支援,即不支援向 bundle 進行 git push

BUNDLE 格式

Bundle 是 .pack 檔案(參見 git-pack-objects[1]),帶有指示 bundle 中包含哪些引用的頭資訊。

與打包的存檔格式本身一樣,bundle 可以是自包含的,也可以使用排除項建立。請參閱下面的“物件先決條件”部分。

使用修訂排除項建立的 Bundle 是使用 git-pack-objects[1]--thin 選項建立的“瘦 pack”,並使用 git-index-pack[1]--fix-thin 選項解包。

在使用修訂排除項時,沒有建立“厚 pack”的選項,使用者不必擔心其中的區別。透過使用“瘦 pack”,使用排除項建立的 Bundle 大小更小。它們底層是“瘦”的,這一點在此僅作為一種奇聞和對其他文件的引用。

有關更多詳細資訊,請參閱 gitformat-bundle[5],有關“瘦 pack”的討論,請參閱 gitformat-pack[5]

選項

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

用於建立名為 file 的 bundle。這需要 <git-rev-list-args> 引數來定義 bundle 的內容。options 包含 git bundle create 子命令的特定選項。如果 file-,則 bundle 將寫入 stdout。

verify <file>

用於檢查 bundle 檔案是否有效,並且是否能幹淨地應用於當前倉庫。這包括對 bundle 格式本身的檢查,以及檢查先決條件提交是否存在並已完全連結到當前倉庫。然後,git bundle 會打印出缺失的提交列表(如果有)。最後,還會列印有關其他功能(如“物件過濾器”)的資訊。有關更多資訊,請參閱 gitformat-bundle[5] 中的“功能”部分。退出程式碼為零表示成功,否則表示 bundle 檔案無效。如果 file-,則從 stdin 讀取 bundle。

list-heads <file>

列出 bundle 中定義的引用。如果後面跟著一個引用列表,則只打印匹配給定引用的引用。如果 file-,則從 stdin 讀取 bundle。

unbundle <file>

將 bundle 中的物件傳遞給 git index-pack 以便儲存在倉庫中,然後列印所有已定義引用的名稱。如果給出了引用列表,則只打印列表中匹配的引用。此命令實際上是底層的呼叫命令,僅供 git fetch 呼叫。如果 file-,則從 stdin 讀取 bundle。

<git-rev-list-args>

一個引數列表,可被 git rev-parsegit rev-list 接受(幷包含一個命名引用,請參閱下面的“指定引用”),用於指定要傳輸的特定物件和引用。例如,master~10..master 將當前 master 引用及其第 10 個祖先提交以來的所有新增的物件一起打包。引用的數量和打包的物件數量沒有明確限制。

[<refname>…​]

一個引用列表,用於限制作為可用的引用。這主要用於 git fetch,後者期望只接收請求的引用,而不是 pack 中的所有內容(在這種情況下,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,該 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>

對於下一個示例,假設您想將倉庫 R1(位於機器 A 上)的歷史記錄傳輸到倉庫 R2(位於機器 B 上)。出於某種原因,不允許 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 就像一個常規倉庫,它可以從中獲取或拉取。例如,您可以在獲取時對映引用

$ git fetch mybundle master:localRef

您還可以檢視它提供的引用

$ git ls-remote mybundle

討論

建立倉庫完整備份的一種簡單方法是使用類似 cp -r <repo> <destination> 的命令。不推薦這樣做,因為在複製操作期間倉庫可能會被寫入。反過來,<destination> 中的某些檔案可能會損壞。

這就是為什麼建議使用 Git 工具來製作倉庫備份,無論是使用此命令還是例如 git-clone[1]。但請記住,這些工具不會幫助您備份除引用和提交以外的狀態。換句話說,它們不會幫助您備份索引內容、工作樹、暫存區、每個倉庫的配置、鉤子等。

另請參閱 gitfaq[7],“傳輸”部分,瞭解跨系統進行檔案同步問題的討論。

檔案格式

請參閱 gitformat-bundle[5]

GIT

Git[1] 套件的一部分