簡體   English   中英

減少Bitbucket上git存儲庫的大小

[英]Reduce size of git repository on Bitbucket

經過幾個月(提交和推送)我的項目,存儲庫的大小在Bitbucket上逐漸增加! 它大約是1 GB,我試圖刪除一些不重要的數據庫文件夾。 搜索后我發現大多數建議都是建議:

git filter-branch -f --tree-filter 'rm -rf folder/subfolder' HEAD

刪除幾個文件夾后,我將更改推送到存儲庫 - 強制,如

git push origin master --force

我終於發現每次使用這些命令時存儲庫都會變大!! 可見,存儲庫變大了2.5 GB!

有什么建議嗎?

編輯根據下面的建議,我嘗試了以下命令
(適用於所有大文件)

git filter-branch --index-filter“git rm -rf --cached --ignore-unmatch $ files”--tag-name-filter cat - --all

(刪除臨時歷史git-filter-branch,否則長時間留下)

rm -rf .git / refs / original /

git reflog expire --all
git gc --aggressive --prune

但文件夾.git / objects仍然很大!!!!

好的,鑒於您對評論的回答,我們現在可以說出發生了什么。

git filter-branch作用是您的提交(部分或全部) 復制到新的提交,然后更新引用。 這意味着您的存儲庫變得更大 (不小),至少在最初階段。

復制的提交是通過給定的引用可以訪問的提交。 在這種情況下,你給出的引用是HEAD (git變成“你當前的分支”,可能是master ,但無論你當前的分支是在filter-branch命令時)。 如果(並且僅當)新副本精確地,與原始副本一點一點地相同,那么它實際上原始副本並且沒有實際副本(原件被重新使用)。 但是,只要您進行任何更改 - 例如刪除folder/subfolder ,從這一點開始就是這些副本。

在這種情況下,復制的東西更小,因為你刪除了一些項目。 (它通常不是很小,因為git很好地壓縮項目。)但是你仍然在向存儲庫添加更多東西:新提交,它引用新樹,幸運的是 - 引用相同的舊blob(文件對象)和以前一樣,這次只是少了一些( folder/subfolder文件folder/subfolder文件的對象仍在存儲庫中,但復制的提交和樹對象不再引用它們)。

從圖形上看,在filter-branch過程的這一點上,我們現在都有舊的提交:

R--o--o---o--o   <-- master
    \    /
     o--o        <-- feature

和新的(我假設folder/subfolder出現在原始的根提交R所以我們在這里有一個副本R' ):

R'-o'-o'--o'-o'
    \    /
     o'-o'

在復制過程結束時, filter-branch現在做了什么,重新指向一些引用(主要是分支和標記名稱)。 它重新指出的那些是你告訴它的那些,通過提及它們作為文檔所謂的“積極參考”。 在這種情況下,如果你在master (即HEADmaster另一個名字),你給出的單個正參考是master ...所以這是所有 filter-branch重新點。 它還會生成名稱以refs/original/開頭的備份引用。 這意味着您現在擁有以下提交:

R--o--o---o--o   <-- refs/original/refs/heads/master
    \    /
     o--o        <-- feature

R'-o'-o'--o'-o'  <-- master
    \    /
     o'-o'

請注意,該feature仍然指向所有舊的 (未復制的)提交,因此即使在您刪除任何refs/original/ references之后,git也將保留所有仍然引用的任何垃圾收集活動的提交, :

R--o
    \
     o--o        <-- feature

R'-o'-o'--o'-o'  <-- master
    \    /
     o'-o'

要使filter-branch更新所有引用,您需要將它們全部命名。 一個簡單的方法是使用--all ,它完全命名所有引用。 在這種情況下,最初的“之后”圖片看起來像這樣:

R--o--o---o--o   <-- refs/original/refs/heads/master
    \    /
     o--o        <-- refs/original/refs/heads/feature

R'-o'-o'--o'-o'  <-- master
    \    /
     o'-o'       <-- feature

現在,如果刪除所有refs/original/引用,則所有舊提交都將被取消引用,並且可以進行垃圾回收。 嗯,就是說, 除非有標簽指向它們, 否則它們會這樣做

對於標記引用, filter-branch僅在您提供--tag-name-filter以任何方式更新它們。 通常你需要--tag-name-filter cat ,它保持標簽名稱不變,但是使filter-branch將它們指向新復制的提交。 這樣你就不會掛起舊的提交了:練習的重點是讓一切都使用新的副本,然后丟棄舊的副本,這樣大文件對象就可以被垃圾收集了。


把這一切放在一起,而不是:

git filter-branch -f --tree-filter 'rm -rf folder/subfolder'

您可以使用:

git filter-branch -f --tree-filter 'rm -rf folder/subfolder' \
    --tag-name-filter cat -- --all

(你不需要反斜杠 - 換行符序列;我把它放在只是為了使行更符合stackoverflow。請注意--tree-filter非常慢:對於這種特殊情況,它使用--index-filter要快得多--index-filter 。這里的索引過濾器命令是git rm --cached --ignore-unmatch -r folder/subfolder 。)

另請注意,您需要在原始存儲庫(副本)上執行所有這些操作(您確實保留了備份,對吧?)。 (如果你沒有備份, refs/originals/可能是你的救贖。)


編輯:好的,所以你做了一些filter-branch -ing,你做了一些刪除任何refs/originals/ (在我對temp repo的實驗中,在HEAD上運行git filter-branch使用我所在的任何分支作為重新指向的分支,並創建了前一個值的“原始”副本。)沒有備份庫。 怎么辦?

那么,作為第一步,立即進行備份 這樣,如果事情變得更糟,你至少可以回到“只是稍微糟糕”。 要備份repo,您​​可以簡單地克隆它(或者:克隆它,然后將原始文件稱為“backup”,然后開始處理克隆)。 為了將來參考,由於git filter-branch可能具有很強的破壞性,因此通常可以從這個備份過程開始。 (另外,我會注意到bitbucket上的一個克隆,當還沒有push ed-to時,會服務。不幸的是你做了push 。也許bitbucket可以從他們自己的一些備份或快照中檢索存儲庫的早期版本。)

接下來,讓我們注意一下提交的特性及其SHA-1“真實姓名”,我之前提到過。 提交的SHA-1名稱是其內容的加密校驗和。 讓我們看看git自己的源代碼樹中的一個示例提交(只是為了長度而修剪了一下,並且電子郵件地址被打到了收割機):

$ git cat-file -p 5de7f500c13c8158696a68d86da1030313ddaf69
tree 73eee5d136d2b00c623c3fceceffab85c9e9b47e
parent c4ad00f8ccb59a0ae0735e8e32b203d4bd835616
author Jeff King <peff peff.net> 1405233728 -0400
committer Junio C Hamano <gitster pobox.com> 1406567673 -0700

alloc: factor out commit index

We keep a static counter to set the commit index on newly
allocated objects. However, since we also need to set the
[snip]

在這里,我們可以看到此提交的內容(其“真實名稱”為5de7f50... )以tree和另一個SHA-1, parent和另一個SHA-1, authorcommitter ,然后是空行然后是提交消息文本。

如果你看一tree你會看到它包含子樹(子目錄)的“真實名字”(SHA-1值)和文件對象(git術語中的“blob”)及其模式 -實際上,只是blob是否應該具有執行權限集,以及它們在目錄中的名稱。 例如,上面tree的第一行是:

100644 blob 5e98806c6cc246acef5f539ae191710a0c06ad3f    .gitattributes

這意味着應該提取存儲庫對象5e98806... ,放入名為.gitattributes的文件中,並設置不可執行文件。

如果我要求git進行新的提交,並設置,作為其內容:

  • 同一棵樹( 73eee5d...
  • 同一個父母( c4ad00f...
  • 同一作者和提交人
  • 和相同的空白行和消息

然后,當我得到git將該提交寫入存儲庫時,它將生成相同的“真實名稱” 5de7f50... 換句話說,它實際上是相同的提交:它已經在存儲庫中, git commit-tree將只返回現有的ID。 雖然設置這一切有點棘手,但這正是git filter-branch最終要做的事情:它提取原始提交,應用過濾器,設置所有內容,然后執行git commit-tree

這對你意味着什么

在您的原始倉庫中,您運行了一個git filter-branch命令,該命令將提交復制到新的,已修改的提交(使用不同的tree ,因此,在某些時候,不同的真實名稱會導致后續提交中的不同父ID,依此類推) 。 但是,如果通過應用此次不執行任何操作的過濾器來復制這些復制的提交,則新的tree對象將與舊的tree對象相同 如果新父級是相同的,並且作者,提交者和消息也保持不變,則副本的新提交ID將與舊ID 相同

也就是說,這些副本畢竟不是副本,它們只是原件!

任何其他提交 - 在第一次傳遞中復制的提交都會被復制,因此具有不同的ID。

事情變得棘手。

如果您當前的存儲庫看起來像這樣 (從圖形上講):

R--o--o---o--o   <-- xxx [needs a name so that filter-branch will process it]
    \    /
     o--o        <-- feature

R'-o'-o'--o'-o'  <-- master
    \    /
     o'-o'

我們將這個新的filter-branch所有引用(甚至是“除了master ”之外的所有引用),這次它會生成相同的樹,它會再次復制R並且新樹將與R'匹配,所以副本實際上 R' 然后它將復制第一個后R節點,進行相同的更改,副本實際上是第一個后R'o'節點。 這將重復所有節點,甚至可能包括R'和所有o' 如果filter-branch副本R' ,則生成的副本將再次成為R' ,因為“刪除不存在的目錄”不做任何更改:我們的過濾器對這些特定提交不執行任何操作。

最后,filter-branch將移動標簽,留下refs/originals/ versions:

R--o--o---o--o   <-- refs/originals/refs/xxx
    \    /
     o--o        <-- refs/originals/refs/feature

R'-o'-o'--o'-o'  <-- master, xxx
    \    /
     o'-o'       <-- feature

事實上,這是理想的結果。

如果存儲庫看起來更像這樣怎么辦? 也就是說,如果沒有xxx或類似的標簽指向原始(預過濾) master ,那么你有這個:

R--o
    \
     o--o        <-- feature

R'-o'-o'--o'-o'  <-- master
    \    /
     o'-o'

filter-branch腳本仍然會復制R ,結果仍然是R' 然后,它會復制第一o節點,結果依然會是第一個o'點,依此類推。 它不會復制現在刪除的節點,但它不必:我們已經擁有那些,可通過branch-name master 和以前一樣, filter-branch可以復制R'和各種o'節點,但這沒關系,因為過濾器什么也不做,所以副本實際上只是原件。

最后, filter-branch將像往常一樣更新引用:

R--o
    \
     o--o        <-- refs/originals/refs/feature

R'-o'-o'--o'-o'  <-- master
    \    /
     o'-o'       <-- feature

使這一切工作的關鍵是過濾器保留已修改的提交不變,因此它們的第二個“副本”再次只是第一個副本。 1

完成所有操作后,您可以執行git filter-branch文檔中描述的相同收縮,以拋棄refs/originals/ names並垃圾收集now-unreferenced對象。


1如果你一直在使用一個不那么容易重復的過濾器(例如,以“當前時間”作為時間戳進行新提交的過濾器),你真的需要一個未經修改的原始存儲庫,或那些refs/originals/引用(任何一個都足以保持“原始副本”)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM