2017-04-07 40 views
1

要刪除所有提交歷史的一個大的不必要的文件,您可以使用filter-branch改寫每個指數(文件在回購名單)提交因此從未被添加的文件。重寫提交歷史修改一個文件

git filter-branch --index-filter "git rm --cached --ignore-unmatch path/to/offending_file.wav" --tag-name-filter cat -- --all 

但是,如果我想保留該文件,但讓它小了很多(例如,想象一下,如果一個圖標是一個巨大的圖像存儲意外)的東西。我嘗試這樣的做法:

加上一個替換文件到Git的數據庫

HASH=`git hash-object -w /tmp/replacement.png` 

另外請注意,我們要替換

FILE="path/to/icon.png" 

現在篩選指標如下文件:首先檢查文件存在於此次提交中:

git cat-file -e :"$FILE" 

如果是這樣從索引中刪除它:

git rm --cached "$FILE" 

最後,使用相同的文件名添加對我們替換的引用。

git update-index --add --cacheinfo "100644,$HASH,$FILE" 

全部放在一起:

git filter-branch --index-filter "if git cat-file -e :$FILE ; then git rm --cached $FILE ; git update-index --add --cacheinfo 100644,$HASH,$FILE ; fi" --tag-name-filter cat -- --all 

這似乎是工作,不會打印可太嚇人任何錯誤。但是,無論有多少git gc和prune命令我嘗試原始blob仍然存在於存儲庫中。即使我將回購克隆到一個新的地方,它仍然存在。

我懷疑這是因爲遠程參考,original引用哪個filter-branch創建仍然指向舊的樹,所以原始文件仍然引用。

我曾嘗試用這樣的黑客刪除他們都:

for REF in `git show-ref | cut -c 42- | grep original` ; do git update-ref -d $REF ; done 

與同爲remotes,但斑點仍然存在。

所以我的問題:

  1. 有沒有辦法,看看爲什麼斑被當作垃圾回收?即父母對象在圖中指向它?
  2. 是否有非哈克的方式去除originals裁判(也許該遙控器) - 包括所有的分支和標籤?
  3. 還有什麼我失蹤?
+0

是否有包含這個大文件的_many_提交,這樣手動重寫歷史記錄不是一種現實的可能性? –

+0

是100次提交。 – Timmmm

回答

1

啊哈,我做到了!我認爲。

以下是額外的步驟。首先,它是一個好主意,要注意在開始你想要的BLOB的哈希值,所以你可以檢查它是否與

git cat-file -t 949abcd.... 

好了,所以我首先清除了引用日誌存在,因爲它仍然有原來的克隆的引用:

git reflog expire --expire=now --all 

接下來我刪除了遠程原點,因爲它仍然有一個對原始樹的引用。我猜如果你新哈希(可能需要強制推),那麼這一步將是不必要的,該文件應該最終GCed無論如何。

git remote rm origin 

接着我除去original參(即filter-branch創建)。我沒有找到一個更簡單的方法:

for REF in `git show-ref | cut -c 42- | grep original` ; do git update-ref -d $REF ; done 

最後,垃圾收集。我不確定是否需要--aggressive,但--prune=now肯定是因爲否則git gc只有垃圾收集爲了安全起見,不需要的對象。

git gc --aggressive --prune=now 

經過所有這些步驟git cat-file報告blob消失了!我還沒有嘗試將結果推回原點(在重新添加它之後),並且我不能100%確定上述哪些步驟是必要的,但這似乎工作至今。