有時,我將DVD-rip放入一個網站項目中,而後不當心git commit -a -m ...
,而後,zap的回購膨脹了2.2個演出。 下次我進行一些編輯,刪除視頻文件並提交全部內容,可是壓縮文件仍在歷史記錄中。 html
我知道我能夠從這些提交開始分支,並將一個分支從新創建到另外一個分支。 可是,我應該怎麼作才能將2個提交合並在一塊兒,以便大文件不顯示在歷史記錄中,並在垃圾回收過程當中清除? java
請注意,此命令可能具備很大的破壞性。 若是更多的人在回購上工做,他們都將不得不拉新的樹。 若是您的目標不是減少大小,則不須要三個中間命令。 因爲filter分支會建立已刪除文件的備份,所以能夠在其中保留很長時間。 git
$ git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch YOURFILENAME" HEAD $ rm -rf .git/refs/original/ $ git reflog expire --all $ git gc --aggressive --prune $ git push origin master --force
git filter-branch --tree-filter 'rm -f path/to/file' HEAD
對我來講效果很好,儘管我遇到了與此處所述相同的問題,我經過遵循此建議解決了這個問題。 github
這本pro-git書包含一整章有關重寫歷史的內容 -看看filter-branch
/從「每次提交中刪除文件」部分。 shell
這些命令在個人狀況下有效: c#
git filter-branch --force --index-filter 'git rm --cached -r --ignore-unmatch oops.iso' --prune-empty --tag-name-filter cat -- --all rm -rf .git/refs/original/ git reflog expire --expire=now --all git gc --prune=now git gc --aggressive --prune=now
與上述版本幾乎沒有什麼不一樣。 bash
對於那些須要將其推送到github / bitbucket的用戶(我僅使用bitbucket進行了測試): less
# WARNING!!! # this will rewrite completely your bitbucket refs # will delete all branches that you didn't have in your local git push --all --prune --force # Once you pushed, all your teammates need to clone repository again # git pull will not work
使用BFG Repo-Cleaner ,這是git-filter-branch
一種更簡單,更快的替代方法,專門用於從Git歷史記錄中刪除不須要的文件。 編輯器
認真遵循使用說明 ,核心部分就是這樣: ide
$ java -jar bfg.jar --strip-blobs-bigger-than 100M my-repo.git
任何大小超過100MB的文件(不在您的最新提交中)都將從Git存儲庫的歷史記錄中刪除。 而後,您可使用git gc
清除失效的數據:
$ git gc --prune=now --aggressive
BFG一般比運行git-filter-branch
至少快10-50倍,而且一般更易於使用。
徹底公開:我是BFG Repo-Cleaner的做者。
若是您已將歷史記錄發佈給其餘開發人員,那麼您想要作的就是極具破壞性的。 有關修復歷史記錄後的必要步驟,請參見git rebase
文檔中的「從上游Rebase恢復」 。
您至少有兩個選擇: git filter-branch
和交互式rebase,這兩個都在下面說明。
git filter-branch
我從Subversion導入中獲取大量的二進制測試數據時遇到了相似的問題,並寫了有關從git存儲庫中刪除數據的信息 。
說您的git歷史記錄是:
$ git lola --name-status * f772d66 (HEAD, master) Login page | A login.html * cb14efd Remove DVD-rip | D oops.iso * ce36c98 Careless | A oops.iso | A other.html * 5af4522 Admin page | A admin.html * e738b63 Index A index.html
請注意, git lola
是非標準但很是有用的別名。 使用--name-status
開關,咱們能夠看到與每次提交關聯的樹修改。
在「 Careless」提交(SHA1對象名稱爲ce36c98)中,文件oops.iso
是偶然添加的DVD-rip,並在下一個提交cb14efd中刪除。 使用上述博客文章中描述的技術,要執行的命令是:
git filter-branch --prune-empty -d /dev/shm/scratch \ --index-filter "git rm --cached -f --ignore-unmatch oops.iso" \ --tag-name-filter cat -- --all
選項:
--prune-empty
刪除因爲過濾操做而變爲空的提交( 即 ,不更改樹)。 在典型狀況下,此選項會產生更清晰的歷史記錄。 -d
命名一個臨時目錄,該目錄尚不用於構建過濾的歷史記錄。 若是您在現代Linux發行版上運行,則在/dev/shm
指定樹將加快執行速度 。 --index-filter
是主要事件,在歷史記錄的每一步都針對索引運行。 您但願刪除oops.iso
不管它在哪裏找到,但並不是全部提交中都存在。 git rm --cached -f --ignore-unmatch oops.iso
刪除存在的DVD-rip,不然不會失敗。 --tag-name-filter
描述瞭如何重寫標籤名稱。 cat
的過濾器是身份操做。 您的存儲庫與上面的示例同樣,可能沒有任何標籤,可是出於全面考慮,我包括了此選項。 --
指定git filter-branch
選項的結尾 --all
如下--
是全部裁判的簡寫。 像上面的示例同樣,您的存儲庫可能只有一個ref(主文件),可是出於全面考慮,我包括了此選項。 通過一番攪拌,如今的歷史是:
$ git lola --name-status * 8e0a11c (HEAD, master) Login page | A login.html * e45ac59 Careless | A other.html | * f772d66 (refs/original/refs/heads/master) Login page | | A login.html | * cb14efd Remove DVD-rip | | D oops.iso | * ce36c98 Careless |/ | A oops.iso | A other.html * 5af4522 Admin page | A admin.html * e738b63 Index A index.html
請注意,新的「 Careless」提交僅添加other.html
,而「 Remove DVD-rip」提交再也不位於master分支上。 標爲refs/original/refs/heads/master
的分支包含您的原始提交,以防您出錯。 要刪除它,請按照「收縮存儲庫清單」中的步驟進行操做。
$ git update-ref -d refs/original/refs/heads/master $ git reflog expire --expire=now --all $ git gc --prune=now
對於更簡單的選擇,克隆存儲庫以丟棄不須要的位。
$ cd ~/src $ mv repo repo.old $ git clone file:///home/user/src/repo.old repo
使用file:///...
克隆URL複製對象而不是僅建立硬連接。
如今您的歷史記錄是:
$ git lola --name-status * 8e0a11c (HEAD, master) Login page | A login.html * e45ac59 Careless | A other.html * 5af4522 Admin page | A admin.html * e738b63 Index A index.html
前兩個提交(「索引」和「管理頁面」)的SHA1對象名稱保持不變,由於過濾操做未修改這些提交。 「 Careless」丟失了oops.iso
,「 Login page」有了新的父代,所以其SHA1 確實發生了變化。
具備如下歷史:
$ git lola --name-status * f772d66 (HEAD, master) Login page | A login.html * cb14efd Remove DVD-rip | D oops.iso * ce36c98 Careless | A oops.iso | A other.html * 5af4522 Admin page | A admin.html * e738b63 Index A index.html
您想從「無憂無慮」中刪除oops.iso
,就好像您從未添加過它同樣,而後「刪除DVD-rip」對您毫無用處。 所以,咱們計劃進行交互式基礎調整的是保留「管理員頁面」,編輯「無憂無慮」並丟棄「刪除DVD-rip」。
運行$ git rebase -i 5af4522
啓動具備如下內容的編輯器。
pick ce36c98 Careless pick cb14efd Remove DVD-rip pick f772d66 Login page # Rebase 5af4522..f772d66 onto 5af4522 # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. #
執行咱們的計劃,咱們將其修改成
edit ce36c98 Careless pick f772d66 Login page # Rebase 5af4522..f772d66 onto 5af4522 # ...
也就是說,咱們用「 Remove DVD-rip」刪除該行,並將「 Careless」上的操做更改成edit
而不是pick
。
保存退出編輯器後,在命令提示符處顯示如下消息。
Stopped at ce36c98... Careless You can amend the commit now, with git commit --amend Once you are satisfied with your changes, run git rebase --continue
消息告訴咱們,咱們處於咱們要編輯的「 Careless」提交中,所以咱們運行兩個命令。
$ git rm --cached oops.iso $ git commit --amend -C HEAD $ git rebase --continue
第一個從索引中刪除有問題的文件。 第二個將「 Careless」修改或修改成更新的索引,而且-C HEAD
指示git重用舊的提交消息。 最後, git rebase --continue
繼續進行其他的rebase操做。
這提供瞭如下歷史記錄:
$ git lola --name-status * 93174be (HEAD, master) Login page | A login.html * a570198 Careless | A other.html * 5af4522 Admin page | A admin.html * e738b63 Index A index.html
這就是你想要的。