我正在尋找有關如何處理源代碼(Web應用程序)所依賴的大型二進制文件的意見。 咱們目前正在討論幾種替代方法: python
您對此有何經驗/想法? git
另外:是否有人在多個Git存儲庫中進行過管理並在一個項目中進行管理? github
這些文件是程序的圖像,該程序會在其中生成包含這些文件的PDF。 文件不會常常更改(像幾年同樣),可是它們與程序很是相關。 沒有文件,該程序將沒法運行。 bash
您也可使用git-fat 。 我喜歡它僅取決於rsync
Python和rsync
。 它還經過如下自我說明命令來支持一般的Git工做流程: 服務器
git fat init git fat push git fat pull
另外,您須要將.gitfat文件檢入到存儲庫中,並修改.gitattributes以指定要由git fat
管理的文件擴展名。 ssh
您可使用普通的git add
添加二進制文件,後者又會根據您的gitattributes規則調用git fat
。 maven
最後,它的優勢是能夠在存儲庫和用戶之間共享實際存儲二進制文件的位置,並支持rsync
所作的任何事情。 測試
更新:若是您使用的是Git-SVN橋,請不要使用git-fat。 最終將從Subversion存儲庫中刪除二進制文件。 可是,若是您使用的是純Git存儲庫,那麼它的運行效果很好。 fetch
看看camlistore 。 它並非真正基於Git的,可是我發現它更適合您的工做。 gradle
自2015年4月以來的另外一種解決方案是Git大文件存儲(LFS) (由GitHub提供)。
它使用git-lfs (請參閱git-lfs.github.com )並在支持它的服務器上進行了測試: lfs-test-server :
您只能將元數據存儲在git repo中,並將大文件存儲在其餘位置。
我想提出的解決方案基於孤立分支和對標記機制的輕微濫用,此後稱爲*孤立標記二進制存儲(OTABS)
TL; DR 12-01-2017若是可使用github的LFS或其餘第三方,則應採起全部措施。 若是不能,請繼續閱讀。 請注意,此解決方案是駭客,應這樣對待。
OTABS的理想特性
git pull
和git fetch
,包括git fetch --all
仍然對帶寬有效 ,也就是說,默認狀況下並不是全部大型二進制文件都是從遠程提取的。 OTABS的不良特性
git clone
可能效率低下(但不必定取決於您的用法)。 若是部署此解決方案,則可能必須建議您的同事使用git clone -b master --single-branch <url>
代替git clone
。 這是由於git clone默認會從字面上克隆整個存儲庫,包括一般不但願浪費帶寬的內容,例如未引用的提交。 取自SO 4811434 。 git fetch <remote> --tags
帶寬效率低下,但不必定存儲效率低下。 您能夠隨時建議您的同事不要使用它。 git gc
技巧從不須要的文件中清除存儲庫。 添加二進制文件
在開始以前,請確保已提交全部更改,工做樹是最新的,而且索引中不包含任何未提交的更改。 最好將全部本地分支推送到遠程(github等),以防萬一發生災難。
git checkout --orphan binaryStuff
能夠解決問題。 這將產生一個與其餘分支徹底斷開鏈接的分支,而且您將在該分支中進行的第一次提交將沒有父項,這將使其成爲根提交。 git rm --cached * .gitignore
清理索引。 rm -fr * .gitignore
刪除整個工做樹。 內部.git
目錄將保持不變,由於*
通配符與之不匹配。 git fetch
阻塞其鏈接時都將下載它。 您能夠經過推送標籤而不是分支來避免這種狀況。 若是他們習慣鍵入git fetch <remote> --tags
,這仍然會影響您同事的帶寬和文件系統存儲,但請繼續閱讀以尋求解決方法。 繼續並git tag 1.0.0bin
git push <remote> 1.0.0bin
。 git branch -D binaryStuff
。 您的提交不會被標記爲垃圾回收,由於指向它的1.0.0bin
孤兒標記足以使其存活。 簽出二進制文件
git checkout 1.0.0bin -- VeryBigBinary.exe
。 1.0.0bin
,這將失敗,在這種狀況下,您必須事先git fetch <remote> 1.0.0bin
。 VeryBigBinary.exe
添加到母版的.gitignore
,這樣團隊中的任何人都不會偶然用二進制文件污染項目的主要歷史記錄。 徹底刪除二進制文件
若是您決定從本地存儲庫,遠程存儲庫和同事的存儲庫中徹底清除VeryBigBinary.exe,則能夠:
git push <remote> :refs/tags/1.0.0bin
上的孤立標籤git push <remote> :refs/tags/1.0.0bin
git tag -l | xargs git tag -d && git fetch --tags
git tag -l | xargs git tag -d && git fetch --tags
。 取自SO 1841341 ,稍做修改。 git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc "$@"
。 它還將刪除全部其餘未引用的提交。 取自SO 1904860 git clone -b master --single-branch <url>
而不是git clone
不管它們是否在帶寬和存儲方面都不會對您的團隊產生任何影響。 2.0.0bin
的步驟1-8。 若是您擔憂同事鍵入git fetch <remote> --tags
,則實際上能夠將其從新命名爲1.0.0bin
。 這將確保下次他們獲取全部標籤時,不會引用舊的1.0.0bin
並將其標記爲後續垃圾回收(使用步驟3)。 當您嘗試覆蓋遠程服務器上的標籤時,您必須像這樣使用-f
: git 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_bin
, tuesday_bin
,..., friday_bin
和一個孤立標記中對於每一個版本1.7.8bin
2.0.0bin
等。您能夠旋轉weekday_bin
並天天刪除舊的二進制文件。 這樣,您能夠充分利用兩個世界:保留源代碼的整個歷史記錄,但僅保留二進制依賴項的相關歷史記錄。 獲取給定標籤的二進制文件也很容易, 而無需獲取全部帶有其全部歷史記錄的源代碼: git init && git remote add <name> <url> && git fetch <name> <tag>
應該爲您完成。
SVN彷佛比Git更有效地處理二進制增量。
我必須決定用於文檔的版本控制系統(JPEG文件,PDF文件和.odt文件)。 我剛剛測試了添加JPEG文件並將其旋轉90度四次(以檢查二進制增量的有效性)。 Git的存儲庫增加了400%。 SVN的存儲庫僅增加了11%。
所以,看起來SVN與二進制文件相比效率更高。
所以,個人選擇是對源代碼使用Git,對文檔等二進制文件使用SVN。