簡體中文 ▾ 主題 ▾ 最新版本 ▾ 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