如何使用 Git 管理二進制大物件

5 位讀者喜歡這篇文章。
Databases as a service

Jason Baker。CC BY-SA 4.0。

閱讀

在本系列的前六篇文章中,我們學習了如何使用 Git 管理文字檔案的版本控制。但是二進制檔案呢?Git 具有處理多媒體檔案等二進制大物件的擴充功能,因此今天我們將學習如何使用 Git 管理二進制資產。

大家似乎都同意一件事,那就是 Git 不太適合大型二進制大物件。請記住,二進制大物件與大型文字檔案不同;您可以在大型文字檔案上使用 Git 而不會出現問題,但 Git 對於無法穿透的二進制檔案無能為力,只能將其視為一個巨大的黑色方塊並按原樣提交。

假設您有一個複雜的 3D 模型,用於您正在製作的令人興奮的新第一人稱益智遊戲,並且您將其儲存為二進制格式,產生了一個 1 GB 的檔案。您執行 git commit 一次,將 1 GB 新增到儲存庫的歷史記錄中。稍後,您為模型設計了不同的髮型並提交了更新;Git 無法區分頭髮與頭部或模型的其餘部分,因此您剛剛提交了另一個 GB。然後您更改了模型的眼睛顏色並提交了這個小小的更改:又一個 GB。這是一個模型的三個 GB,僅進行了一些微小的隨意更改。將其擴展到遊戲中的所有資產,您就會遇到嚴重的問題。

將其與 .obj 格式等文字檔案進行比較。一個提交儲存了所有內容,就像另一個模型一樣,但 .obj 檔案是一系列描述模型頂點的純文字行。如果您修改模型並將其儲存回 .obj,Git 可以逐行讀取這兩個檔案,建立更改的差異,並處理一個相當小的提交。模型越精細,提交就越小,這是一個標準的 Git 用例。它是一個很大的檔案,但它使用一種覆蓋或稀疏儲存方法來建構資料目前狀態的完整圖片。

但是,並非所有內容都以純文字形式運作,而且現在每個人都想使用 Git。因此需要一個解決方案,並且已經出現了幾個解決方案。

Git Large File Storage (LFS) 是 GitHub 的一個開源專案,最初是 git-media 的一個分支。Git-media 和 git-annex 是 Git 的擴充功能,旨在管理大型檔案。它們是解決同一個問題的兩種不同方法,並且它們各有優勢。這些不是專案本身的官方聲明,但在我的經驗中,它們各自的獨特之處是

  • Git-annex 傾向於分散式模型;您和您的使用者建立儲存庫,並且每個儲存庫都有一個本機 .git/annex 目錄,用於儲存大型檔案。附件會定期同步,以便所有使用者在需要時都可以使用所有資產。除非使用 annex-cost 另行配置,否則 git-annex 優先使用本機儲存,然後才是異地儲存。

  • Git-portal 也是分散式的,並且像 Git-annex 一樣,可以選擇同步到中央位置。它使用您可能已安裝的常用工具(特別是 Bash、Git、rsync)。

  • Git-LFS 是一個集中式模型,用於儲存常用資產的儲存庫。您告訴 Git-LFS 大型檔案的儲存位置,無論是硬碟、伺服器還是雲端儲存服務,並且專案中的每個使用者都將該位置視為大型資產的中央主位置。

git-portal

Git-portal 使用標準 UNIX 工具(如 Bash、Git 本身以及可選的 rsync)為 Git 提供簡化的二進制大物件管理。它將大型二進制檔案複製到本機或遠端儲存,並將它們替換為您可以與專案檔案的其餘部分一起提交的符號連結。

Git-portal 很簡單,但有時需要更多手動操作(例如,它沒有自動垃圾回收)。它非常適合需要管理通常不適合 Git 管理的大型檔案,但又不想學習全新系統的使用者。Git-portal 模仿 Git 本身,因此只有最少的學習曲線。

您可以從 Gitlab 上的專案頁面安裝 Git-portal:Gitlab

所有 Git-portal 命令都與 Git 本身鏡像。要在專案中使用 Git-portal

$ git-portal init

要新增檔案

$ git-portal add bigfile.png

一旦檔案被「傳送到入口網站」(在專案的術語中),您與 Git 的互動與往常完全相同。您可以像往常一樣新增檔案,相對地忽略了其中一些檔案實際上是指向 _portal 目錄的符號連結。

_portal 目錄中的所有內容(完全被 Git 忽略)都可以單獨備份到您喜歡的任何類型的儲存裝置,無論是 USB 磁碟機還是遠端伺服器。由於 Git-portal 提供了一些 Git 鉤子(由特定 Git 動作觸發的自動化腳本,例如推送或拉取),您甚至可以設定一個特殊的 Git 遠端條目,以便您的 _portal 目錄與遠端位置自動同步

$ git remote add _portal alice@myserver.com:/home/alice/umbrella.git/_portal

Git-portal 的優點是它是一個簡單且 Linux 原生的系統。憑藉相當少的常用工具堆疊和只需記住的幾個額外命令,您可以管理大型專案依賴項,甚至在協作者之間共享它們。Git-portal 已在媒體專案、獨立電玩遊戲和遊戲部落格中使用,以管理從小型啟動畫面影像到大型 PDF 檔案,甚至更大的 3D 模型等所有內容。

git-annex

git-annex 具有稍微不同的工作流程,並且預設為本機儲存庫,但基本概念是相同的。您應該能夠從發行版的儲存庫安裝 git-annex,或者您可以根據需要從網站取得它。與 git-media 一樣,任何使用 git-annex 的使用者都必須在其機器上安裝它。

初始設定比 git-media 更簡單。要在伺服器上建立裸儲存庫,請執行以下命令,並替換您自己的路徑

$ git init --bare --shared /opt/jupiter.git

然後將其複製到您的本機電腦上,並將其標記為 git-annex 位置

$ git clone seth@example.com:/opt/jupiter.clone 
Cloning into 'jupiter.clone'... warning: You appear to have cloned
an empty repository. Checking connectivity... done. 
$ git annex init "seth workstation" init seth workstation ok 

您無需使用篩選器來識別媒體資產或大型檔案,而是透過使用 git annex 命令來配置將哪些內容分類為大型檔案

$ git annex add bigblobfile.flac
add bigblobfile.flac (checksum) ok
(Recording state in Git...) 

提交照常進行

$ git commit -m 'added flac source for sound fx'

但是推送是不同的,因為 git annex 使用自己的分支來追蹤資產。您進行的第一次推送可能需要 -u 選項,具體取決於您如何管理儲存庫

$ git push -u origin master git-annex 
To seth@example.com:/opt/jupiter.git 
* [new branch] master -> master 
* [new branch] git-annex -> git-annex 

git-media 一樣,普通的 git push 不會 將您的資產複製到伺服器,它只會傳送有關媒體的資訊。當您準備好與團隊的其餘成員共享您的資產時,請執行同步命令

$ git annex sync --content

如果其他人已將資產共享到伺服器,並且您需要拉取它們,則 git annex sync 將提示您的本機結帳拉取您的機器上不存在但在伺服器上存在的資產。

Git annex 是一個經過微調的解決方案,靈活且使用者友善。它既穩健又經過充分測試。

git-lfs

git-lfs 是用 Go 語言編寫的,您可以從原始碼或可下載的二進制檔案安裝它。說明位於 網站上。每個想要使用 git-lfs 的使用者都需要安裝它,但它是跨平台的,因此通常不會造成問題。

安裝 git-lfs 後,您可以設定要讓 Git 忽略並讓 Git-LFS 管理哪些檔案類型。例如,要讓 Git-LFS 追蹤所有 .png 檔案

$ git lfs track "*.png"

每次您為 Git-LFS 追蹤新增檔案類型時,都必須新增然後提交檔案 .gitattributes

$ git add .gitattributes
$ git commit -m "LFS track *.png"

當您暫存這些類型的檔案時,該檔案會複製到 .git/lfs

Git-LFS 是 Github 的一個專案,並且與 Github 的基礎架構緊密結合。如果您想要執行允許 Git-LFS 整合的 Git 伺服器,您可以研究 Git-LFS 伺服器規格(也是用 Go 語言編寫的)並實作 API。

git-portalgit-annex 都很靈活,並且可以使用本機儲存庫而不是伺服器,因此它們對於管理私人本機專案也同樣有用。

大型檔案和 Git

雖然 Git 是為文字檔案而設計的,但這並不意味著僅僅因為您有二進制資產就不能使用它。有非常好的解決方案可以幫助您管理大型檔案。如果您想使用 Git,真的沒有太多藉口不使用它,所以今天就試試看!

標籤
Seth Kenlon
Seth Kenlon 是一位 UNIX 極客、自由文化倡導者、獨立多媒體藝術家和 D&D 迷。他曾在電影和電腦產業工作,而且常常同時進行。

8 評論

我對任何大型檔案支援方案的困難在於(就我所知),您實際上並沒有對任何資產進行版本控制。當然,您有大型檔案,並且有您所做更改的日誌,但除非我誤解了一些基本內容,否則沒有任何機制可以將這些大型二進制檔案回滾到以前的版本。這對我來說是一個決定性因素,因為分支和回滾能力是我使用版本控制的兩個主要原因。

簡而言之,請告訴我我錯了。Git LFS、git-media 或 git-annex 是否支援分支和回滾大型二進制檔案,而只是文件寫得太晦澀難懂?還是我,可悲的是,正確地理解了文件?

做了一些研究,但事實證明我錯了。大型檔案*確實*被版本控制...修訂版只是單獨儲存。我現在明白了。當您執行結帳時,您只會取得該修訂版/分支所需的檔案。但是,如果您在沒有中央伺服器的情況下進行臨時版本控制(也就是說,就地版本控制專案,而不一定與任何人共享/協作),則設定起來可能會有點麻煩...也許。我想只有一種方法可以確定。:)

回覆 作者:Alexander Teterkin

現在來吹毛求疵一下:有版本控制,然後還有版本控制。對於我管理的大物件,當其他所有內容都處於 33md6465b3 時,讓 git「知道」昨天發生了一些變化對我沒有什麼好處。我不需要我的圖形或視訊版本與昨天的提交相符。我不需要能夠逐步瀏覽我的專案並查看視覺效果的不同階段。我想要備份,以防我完全毀壞了圖形,但除此之外,我不需要版本。然而,git-lfs 確實對大型檔案進行版本控制,這很酷,但這不是我需要的。事實上,當 git-media 和 git-annex 過於繁瑣時,我實際上推出了自己的 BASH 解決方案來簡化流程。

回覆 作者:Jason van Gumster

您知道嗎?「blob」代表「二進制大物件」。

「二進制大物件」因此是二進制二進制大物件

這對我來說是一個決定性因素,因為分支和回滾能力是我使用版本控制的兩個主要原因。對於我管理的大物件,當其他所有內容都處於 33md6465b3 時,讓 git「知道」昨天發生了一些變化對我沒有什麼好處

Creative Commons License本作品採用創用 CC 姓名標示-相同方式分享 4.0 國際許可協議授權。
© . All rights reserved.