使用Git管理大型二進制文件

我正在尋找有關如何處理源代碼(Web應用程序)所依賴的大型二進制文件的意見。 咱們目前正在討論幾種替代方法: python

  1. 手動複製二進制文件。
    • 優勢:不肯定。
    • 相反:我強烈反對這一點,由於它在創建新站點/遷移舊站點時增長了出錯的可能性。 創建另外一個障礙。
  2. Git管理它們。
    • 專業版:消除了「忘記」複製重要文件的可能性
    • 相反:膨脹存儲庫並下降管理代碼庫的靈活性,而檢出,克隆等將花費至關長的時間。
  3. 單獨的存儲庫。
    • 優勢:簽出/克隆源代碼比以往任什麼時候候都快,而且圖像已正確存儲在其本身的存儲庫中。
    • 相反:消除了在項目上擁有惟一的 Git存儲庫的簡單性。 它確定會引入其餘我從未想過的東西。

您對此有何經驗/想法? git

另外:是否有人在多個Git存儲庫中進行過管理並在一個項目中進行管理? github

這些文件是程序的圖像,該程序會在其中生成包含這些文件的PDF。 文件不會常常更改(像幾年同樣),可是它們與程序很是相關。 沒有文件,該程序將沒法運行。 bash


#1樓

您也可使用git-fat 。 我喜歡它僅取決於rsync Python和rsync 。 它還經過如下自我說明命令來支持一般的Git工做流程: 服務器

git fat init
git fat push
git fat pull

另外,您須要將.gitfat文件檢入到存儲庫中,並修改.gitattributes以指定要由git fat管理的文件擴展名。 ssh

您可使用普通的git add添加二進制文件,後者又會根據您的gitattributes規則調用git fatmaven

最後,它的優勢是能夠在存儲庫和用戶之間共享實際存儲二進制文件的位置,並支持rsync所作的任何事情。 測試

更新:若是您使用的是Git-SVN橋,請不要使用git-fat。 最終將從Subversion存儲庫中刪除二進制文件。 可是,若是您使用的是純Git存儲庫,那麼它的運行效果很好。 fetch


#2樓

看看camlistore 。 它並非真正基於Git的,可是我發現它更適合您的工做。 gradle


#3樓

自2015年4月以來的另外一種解決方案是Git大文件存儲(LFS) (由GitHub提供)。

它使用git-lfs (請參閱git-lfs.github.com )並在支持它的服務器上進行了測試: lfs-test-server
您只能將元數據存儲在git repo中,並將大文件存儲在其餘位置。

https://cloud.githubusercontent.com/assets/1319791/7051226/c4570828-ddf4-11e4-87eb-8fc165e5ece4.gif


#4樓

我想提出的解決方案基於孤立分支和對標記機制的輕微濫用,此後稱爲*孤立標記二進制存儲(OTABS)

TL; DR 12-01-2017若是可使用github的LFS或其餘第三方,則應採起全部措施。 若是不能,請繼續閱讀。 請注意,此解決方案是駭客,應這樣對待。

OTABS的理想特性

  • 它是一個純git僅git的解決方案-它無需任何第三方軟件(如git-annex)或第三方軟件(如github的LFS)便可完成工做。
  • 有效地存儲二進制文件,即不會使存儲庫的歷史膨脹。
  • git pullgit fetch ,包括git fetch --all仍然對帶寬有效 ,也就是說,默認狀況下並不是全部大型二進制文件都是從遠程提取的。
  • 它能夠在Windows上運行
  • 它將全部內容存儲在一個git倉庫中
  • 它容許刪除過期的二進制文件(與bup不一樣)。

OTABS的不良特性

  • 它使git clone可能效率低下(但不必定取決於您的用法)。 若是部署此解決方案,則可能必須建議您的同事使用git clone -b master --single-branch <url>代替git clone 。 這是由於git clone默認會從字面上克隆整個存儲庫,包括一般不但願浪費帶寬的內容,例如未引用的提交。 取自SO 4811434
  • 它使git fetch <remote> --tags帶寬效率低下,但不必定存儲效率低下。 您能夠隨時建議您的同事不要使用它。
  • 您將必須按期使用git gc技巧從不須要的文件中清除存儲庫。
  • 它不如bupgit-bigfiles有效 。 可是它分別更適合您要嘗試的操做和更現成的。 您可能會遇到成千上萬個小文件或千兆字節範圍內的文件的麻煩,但請繼續閱讀以獲取解決方法。

添加二進制文件

在開始以前,請確保已提交全部更改,工做樹是最新的,而且索引中不包含任何未提交的更改。 最好將全部本地分支推送到遠程(github等),以防萬一發生災難。

  1. 建立一個新的孤立分支。 git checkout --orphan binaryStuff能夠解決問題。 這將產生一個與其餘分支徹底斷開鏈接的分支,而且您將在該分支中進行的第一次提交將沒有父項,這將使其成爲根提交。
  2. 使用git rm --cached * .gitignore清理索引。
  3. 深呼吸,使用rm -fr * .gitignore刪除整個工做樹。 內部.git目錄將保持不變,由於*通配符與之不匹配。
  4. 複製到您的VeryBigBinary.exe或VeryHeavyDirectory /中。
  5. 添加並提交。
  6. 如今,它變得棘手-若是將它做爲一個分支推送到遠程,則全部開發人員在下次調用git fetch阻塞其鏈接時都將下載它。 您能夠經過推送標籤而不是分支來避免這種狀況。 若是他們習慣鍵入git fetch <remote> --tags ,這仍然會影響您同事的帶寬和文件系統存儲,但請繼續閱讀以尋求解決方法。 繼續並git tag 1.0.0bin
  7. 推送您的孤兒標籤git push <remote> 1.0.0bin
  8. 如此一來,您就永遠不會意外推送二進制分支,能夠將其刪除git branch -D binaryStuff 。 您的提交不會被標記爲垃圾回收,由於指向它的1.0.0bin孤兒標記足以使其存活。

簽出二進制文件

  1. 我(或個人同事)如何將VeryBigBinary.exe檢出到當前工做樹中? 例如,若是您當前的工做分支是master,則能夠簡單地git checkout 1.0.0bin -- VeryBigBinary.exe
  2. 若是您沒有下載孤兒標籤1.0.0bin ,這將失敗,在這種狀況下,您必須事先git fetch <remote> 1.0.0bin
  3. 您能夠將VeryBigBinary.exe添加到母版的.gitignore ,這樣團隊中的任何人都不會偶然用二進制文件污染項目的主要歷史記錄。

徹底刪除二進制文件

若是您決定從本地存儲庫,遠程存儲庫和同事的存儲庫中徹底清除VeryBigBinary.exe,則能夠:

  1. 刪除遠程git push <remote> :refs/tags/1.0.0bin上的孤立標籤git push <remote> :refs/tags/1.0.0bin
  2. 本地刪除孤立標記(刪除全部其餘未引用的標記) git tag -l | xargs git tag -d && git fetch --tags git tag -l | xargs git tag -d && git fetch --tags 。 取自SO 1841341 ,稍做修改。
  3. 使用git gc技巧在本地刪除您如今未引用的提交。 git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc "$@" 。 它還將刪除全部其餘未引用的提交。 取自SO 1904860
  4. 若是可能,請在遙控器上重複git gc技巧。 若是您是自託管存儲庫,則多是這樣,而某些git提供程序(例如github)或某些公司環境中可能沒法實現。 若是您使用的服務提供商託管的ssh不能使您遠程訪問ssh,請放手。 您的提供商的基礎結構可能會在本身的美好時光中清理未引用的提交。 若是您在公司環境中,則能夠建議IT部門執行cron做業垃圾回收,每週大約一次。 只要您建議您的同事始終使用git clone -b master --single-branch <url>而不是git clone不管它們是否在帶寬和存儲方面都不會對您的團隊產生任何影響。
  5. 您全部想擺脫過期的孤兒標籤的同事都只需執行步驟2-3。
  6. 而後,您能夠重複添加二進制文件以建立新的孤立標記2.0.0bin的步驟1-8。 若是您擔憂同事鍵入git fetch <remote> --tags ,則實際上能夠將其從新命名爲1.0.0bin 。 這將確保下次他們獲取全部標籤時,不會引用舊的1.0.0bin並將其標記爲後續垃圾回收(使用步驟3)。 當您嘗試覆蓋遠程服務器上的標籤時,您必須像這樣使用-fgit push -f <remote> <tagname>標籤名git push -f <remote> <tagname>

後記

  • OTABS不會影響您的母版或任何其餘源代碼/開發分支。 提交哈希,全部歷史記錄以及這些分支的較小大小均不受影響。 若是您已經用二進制文件充實了源代碼歷史記錄,則必須將其清理爲單獨的工做。 該腳本可能有用。

  • 確承認以在Windows上使用git-bash使用。

  • 最好應用一組標準度量標準,以使二進制文件的存儲效率更高。 頻繁運行git gc (沒有任何其餘參數)使git經過使用二進制增量來優化文件的基礎存儲。 可是,若是文件從提交到提交的可能性不大,則能夠徹底關閉二進制增量。 此外,因爲壓縮無用的壓縮或加密文件(如.zip,.jpg或.crypt)是沒有意義的,所以git容許您關閉基礎存儲的壓縮。 不幸的是,這是一個全有或全無的設置,也會影響您的源代碼。

  • 您可能須要腳本化OTABS的各個部分,以便更快地使用。 特別地,從徹底刪除二進制文件update git鉤子的腳本步驟2-3能夠爲git fetch(「獲取並刪除全部過時的內容」)提供引人注目的但多是危險的語義。

  • 您可能要跳過「 徹底刪除二進制文件」的第4步,以將全部二進制更改的完整歷史記錄保留在遠程計算機上,而這要付出中央存儲庫膨脹的代價。 隨着時間的流逝,本地存儲庫將保持精簡。

  • 在Java世界中,能夠將此解決方案與maven --offline結合使用,以建立徹底可複製的離線版本,該版本徹底存儲在您的版本控制中(使用maven比使用gradle更容易)。 在Golang世界中,構建此解決方案來管理GOPATH而不是go get是可行的。 在python世界中,能夠將其與virtualenv結合使用以產生一個自包含的開發環境,而無需依賴PyPi服務器進行任何從頭開始的構建。

  • 若是您的二進制文件常常更改,例如生成工件,那麼最好編寫一個腳本解決方案,該解決方案將5個最新版本的工件存儲在孤立標記monday_bintuesday_bin ,..., friday_bin和一個孤立標記中對於每一個版本1.7.8bin 2.0.0bin等。您能夠旋轉weekday_bin並天天刪除舊的二進制文件。 這樣,您能夠充分利用兩個世界:保留源代碼的整個歷史記錄,但僅保留二進制依賴項的相關歷史記錄。 獲取給定標籤的二進制文件也很容易, 而無需獲取全部帶有其全部歷史記錄的源代碼: git init && git remote add <name> <url> && git fetch <name> <tag>應該爲您完成。


#5樓

SVN彷佛比Git更有效地處理二進制增量。

我必須決定用於文檔的版本控制系統(JPEG文件,PDF文件和.odt文件)。 我剛剛測試了添加JPEG文件並將其旋轉90度四次(以檢查二進制增量的有效性)。 Git的存儲庫增加了400%。 SVN的存儲庫僅增加了11%。

所以,看起來SVN與二進制文件相比效率更高。

所以,個人選擇是對源代碼使用Git,對文檔等二進制文件使用SVN。

相關文章
相關標籤/搜索