https://gitbook.tw/chapters/faq/remove-files-from-git.html
https://stackoverflow.com/questions/2164581/remove-file-from-git-repository-history
https://blog.csdn.net/weixin_34392435/article/details/92166474
如何真正移除git文件且不影響版本庫:
方法:使用 Rebase 或 filter-branch 指令來整理
比如git filter-branch
$ git filter-branch --tree-filter "rm -f config/test.c"
Rewrite 27f6ed6da50dbee5adbb68102266a91dc097ad3f (7/7) (0 seconds passed, remaining 0 predicted)
Ref 'refs/heads/master' was rewritten
但這樣的刪除並不徹底,隨時可以恢復文件。
$ git reset refs/original/refs/heads/master --hard
or
$ git reflog&&git checkout $commit-SHA1
因此,需要在git filter-branch之後,繼續執行:
$ git filter-branch -f --tree-filter "rm -f config/test.c" # 個人更使用喜歡參數爲--index-filter,--all filtered all refs; --tag-name-filter cat 刪除原始tag
#回收內存的操作
$ rm .git/refs/original/refs/heads/master # $ rm .git/refs/original 刪除git的備份
$ git reflog expire --all --expire=now #使所有鬆散的object失效
$ git fsck --unreachable #檢查是否有鬆散的object, 驗證數據庫中對象的連接性和有效性
$ git gc --prune=now #git的垃圾清理車最終刪除那些對象 git gc --aggressive --prune=now , --aggressive 此選項將導致git gc更積極地優化存儲庫,但代價是花費更多時間。\
--prune=<date> Prune loose objects older than date 修剪比日期更早的鬆散物體。可以在此之前執行 git repack -A -d 在存儲庫中打包解壓縮的對象。 刪除冗餘的對象
$ git fsck #檢查是否還有對應的object,現在已經找不到提交的sha1了
可以使用該腳本查看大文件(https://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/)
#!/bin/bash
#set -x
# Shows you the largest objects in your repo's pack file.
# Written for osx.
#
# @see https://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/
# @author Antony Stubbs
# set the internal field spereator to line break, so that we can iterate easily over the verify-pack output
IFS=$'\n';
# list all objects including their size, sort by size, take top 10 查出已刪除的大文件前10名的commit SHA值
objects=`git verify-pack -v .git/objects/pack/pack-*.idx | grep -v chain | sort -k3nr | head`
echo "All sizes are in kB's. The pack column is the size of the object, compressed, inside the pack file."
output="size,pack,SHA,location"
for y in $objects
do
# extract the size in bytes
size=$((`echo $y | cut -f 5 -d ' '`/1024))
# extract the compressed size in bytes
compressedSize=$((`echo $y | cut -f 6 -d ' '`/1024))
# extract the SHA
sha=`echo $y | cut -f 1 -d ' '`
# find the objects location in the repository tree
other=`git rev-list --all --objects | grep $sha`
#lineBreak=`echo -e "\n"`
output="${output}\n${size},${compressedSize},${other}"
done
echo -e $output | column -t -s ', '
git filter-branch -- 重寫 branches
https://cloud.tencent.com/developer/section/1138641
git filter-branch [--env-filter <command>][--tree-filter <command>][--index-filter <command>][--parent-filter <command>]
[--msg-filter <command>][--commit-filter <command>][--tag-name-filter <command>][--subdirectory-filter <directory>]
[--prune-empty][--original <namespace>][-d <directory>][-f|--force][--][<rev-list options>…]
--env-filter <command> #修改將在其中執行提交的環境,常用於重寫作者/提交者名稱/電子郵件/時間環境變量。\
(GIT_AUTHOR_NAME,GIT_AUTHOR_EMAIL,GIT_AUTHOR_DATE,GIT_COMMITTER_NAME,GIT_COMMITTER_EMAIL,GIT_COMMITTER_DATE) e.g.
git filter-branch --env-filter '
if test "$GIT_AUTHOR_EMAIL" = "root@localhost"
then
[email protected]
export GIT_AUTHOR_EMAIL
fi
if test "$GIT_COMMITTER_EMAIL" = "root@localhost"
then
[email protected]
export GIT_COMMITTER_EMAIL
fi
' -- --all
--tree-filter <command> #用於重寫tree及其內容的過濾器。新增或刪除文檔
--index-filter <command> #重寫索引的過濾器。類似於樹過濾器,但不檢出樹,因此速度更快。經常與結合使用git rm --cached --ignore-unmatch ...
##--tree-filter將每個提交簽出到臨時目錄中,運行filter命令,並從臨時目錄中的任何內容生成新的提交;
##而--index-filter將每個提交複製到索引中,運行filter命令,並從索引中的任何內容生成新的提交。
--parent-filter <command> #用於重寫提交的父列表的過濾器。它將在stdin上接收父字符串,並在stdout上輸出新的父字符串。
--msg-filter <command> #重寫提交消息。
--commit-filter <command> #執行提交的過濾器
--tag-name-filter <command> #重寫標籤名稱,原始標籤不會被刪除,但可以被覆蓋;使用“ --tag-name-filter cat”來簡單地更新標籤。\
在這種情況下,請格外小心,並確保備份了舊標籤,以防轉換失敗。
--subdirectory-filter <directory> #只查看涉及給定子目錄的歷史記錄
--prune-empty #過濾常常生成空的提交,從而使樹保持不變。此參會刪除空提交。因此僅適用於只有一個父對象的提交它將保留合併點。與--commit-filter不兼容。
--original <namespace> #使用此選項設置原始提交將存儲在其中的名稱空間。默認值是refs/original。
-d <directory> #使用此選項可將路徑設置爲用於重寫的臨時目錄。使用tree-filter, 該命令需要暫時將該樹檢出到某個目錄,大型項目的情況下可能消耗很大空間。
默認情況下,它在.git-rewrite/目錄中執行此操作,但您可以通過此參數覆蓋該選項。
-f/--force #git filter-branch拒絕從現有的臨時目錄開始過濾,或者當已經有ref時refs/original/,使用該參數強制執行過濾。
<rev-list options>… #參數git rev-list。
#所有positive refs都被重寫。您也可以指定選項--all,但您必須使用--將修訂選項與git filter-branch選項分開。--all重寫所有分支和標記。