Git清理刪除歷史提交文件

Git清理刪除歷史提交文件

既然來到這里,想必你認(rèn)為你的Git工程已經(jīng)處于臃腫狀態(tài)了拿愧,一些很久之前引入的大文件,而現(xiàn)在又不用這些大文件的情況下昏翰,請(qǐng)不要遲疑進(jìn)行清理操作。

常見的Git清理方式有兩種舍咖,一種是使用BFG工具矩父,另外一種是使用git filter-branch手動(dòng)處理。

注意:無論使用哪種方式排霉,都涉及破壞性操作,使用時(shí)應(yīng)嚴(yán)格謹(jǐn)慎民轴。在開始操作之前攻柠,請(qǐng)使用--mirror參數(shù)克隆備份你的Git倉(cāng)庫(kù)。

使用BFG的方式后裸,簡(jiǎn)單易操作瑰钮,使用方法可參考BFG Repo-Cleaner

本文主要介紹的是使用 git filter-branch 的方式進(jìn)行瘦身操作微驶。

為了模擬整個(gè)過程浪谴,讓我們先從一個(gè)從0到1的demo開始吧。

1.建立遠(yuǎn)程倉(cāng)庫(kù)

為了模擬團(tuán)隊(duì)協(xié)作因苹,需要一個(gè)遠(yuǎn)程倉(cāng)庫(kù)苟耻,可以選擇GitHub或碼云上建立倉(cāng)庫(kù),這里選擇碼云 扶檐,倉(cāng)庫(kù)名字為 gitthin凶杖,地址為 git@gitee.com:coderhony/gitthin.git

2.克隆到本地

通過Terminal款筑,把剛才新建的代碼文件克隆到本地智蝠。

$ cd ~/Desktop/
$ mkdir gitthin && cd gitthin
$ git clone git@gitee.com:coderhony/gitthin.git

此時(shí)在Desktop的gitthin文件夾下,就有一份Git管理的倉(cāng)庫(kù)了奈梳。

3.基本操作

$ cd gitthin
$ echo -n "戰(zhàn)國(guó)是一個(gè)群國(guó)爭(zhēng)雄的時(shí)代杈湾,今天的故事就從戰(zhàn)國(guó)開始" > zhanguo.txt
$ git add .
$ git commit -m "創(chuàng)建了zhanguo.txt文件"
$ echo -n "戰(zhàn)國(guó)的開端是由趙魏韓三家分晉開始,從此戰(zhàn)國(guó)進(jìn)入七雄爭(zhēng)霸的時(shí)代" >> zhanguo.txt
$ git add .
$ git commit -m "戰(zhàn)國(guó)開端"
$ echo -n "這七個(gè)國(guó)家分別是:秦攘须、齊漆撞、楚、燕阻课、魏叫挟、趙、韓" >> zhanguo.txt
$ git add .
$ git commit -m "七個(gè)國(guó)家的名字"
$ echo -n "秦國(guó)地處西陲限煞,楚國(guó)位居南方抹恳,齊國(guó)傲居?xùn)|海,燕國(guó)地處北面署驻,魏國(guó)奋献、趙國(guó)健霹、韓國(guó)三國(guó)在中間" >> zhanguo.txt
$ git add .
$ git commit -m "七國(guó)的地理位置"

# 切換分支
$ git checkout -b qinguo
$ echo -n "戰(zhàn)國(guó)開始時(shí),秦國(guó)還比較貧弱瓶蚂,一直受東邊的魏國(guó)欺負(fù)糖埋,今天魏國(guó)奪占五城,明天秦國(guó)搶回三城窃这,一直處于這種狀態(tài)" > qinguo.txt
$ git add .
$ git commit -m "創(chuàng)建了qinguo.txt文件"
$ echo -n "當(dāng)時(shí)的魏國(guó)很強(qiáng)大瞳别,魏文侯時(shí)期,啟用李悝變法杭攻,使魏國(guó)經(jīng)濟(jì)富庶祟敛,后來有任用吳起訓(xùn)練魏武卒,一直不斷蠶食著秦國(guó)" >> qinguo.txt
$ git add .
$ git commit -m "秦國(guó)受魏國(guó)欺負(fù)"
$ echo -n "這種情況到秦孝公時(shí)開始有所好轉(zhuǎn)兆解,秦孝公啟動(dòng)商鞅馆铁,進(jìn)行變法,獎(jiǎng)勵(lì)農(nóng)耕锅睛,獎(jiǎng)勵(lì)軍功埠巨,經(jīng)過了二十年,秦國(guó)已不容小覷矣" >> qinguo.txt
$ git add .
$ git commit -m "秦孝公啟用商鞅變法"

4.添加大文件

生成一個(gè)有 1000000 行隨機(jī)字符串的大文本文件

# 大文件來襲
$ perl -le 'for (1..1000000) { print map { (0..9, "a".."z")[rand 36] } 1..80 }' > bigqin
$ git add .
$ git commit -m "商鞅變法现拒,秦國(guó)戰(zhàn)斗力直線上升"

查看大文件情況

$ du -sh .git
55M     .git

可以看到.git的大小為 55M辣垒。

在該大文件的內(nèi)容后面,追加一些內(nèi)容:

$ perl -le 'print map { (0..9, "a".."z")[rand 36] } 1..80' >> bigqin
$ git add .
$ git commit -m "又過幾年具练,秦國(guó)的戰(zhàn)斗力又提高了很多"

查看此時(shí).git文件大小

$ du -sh .git
110M    .git

可以看到乍构,此時(shí).git文件夾的大小變成了110M。

5.繼續(xù)常規(guī)提交

一百多年后扛点,秦國(guó)所向披靡哥遮,橫掃六合,一統(tǒng)天下陵究。

$ echo -n "秦國(guó)變法后一百年眠饮,國(guó)力不斷增強(qiáng),其他諸侯為之色變铜邮,王霸之業(yè)已不能滿足仪召,開始橫掃六合,一統(tǒng)天下松蒜,終于在嬴政時(shí)期得以實(shí)現(xiàn)" >> qinguo.txt
$ git add .
$ git commit -m "秦國(guó)一統(tǒng)天下"

把qinguo分支推送到遠(yuǎn)程:

$ git push origin qinguo

切換到master分支,并繼續(xù)提交代碼

$ git checkout master

$ echo -n "其他六國(guó)不斷被秦國(guó)攻打扔茅,聞之色變,但又沒有及時(shí)變法秸苗,尋求強(qiáng)大之道召娜,之后逐個(gè)被秦國(guó)所滅" >> zhanguo.txt
$ git add .
$ git commit -m "其他六國(guó)逐個(gè)被秦國(guó)所滅"

合并qinguo的內(nèi)容:

$ git merge qinguo

新建分支,并進(jìn)行一些提交

$ git checkout -b chuhan

$ echo -n "秦統(tǒng)一六國(guó)之后,苛捐雜稅不斷加重惊楼,大肆修建宮殿玖瘸,導(dǎo)致百姓痛苦不堪" > chuhan.txt
$ git add .
$ git commit -m "創(chuàng)建了chuhan.txt文件"
$ echo -n "隨著陳勝吳廣起義后秸讹,各國(guó)舊部開始起來反抗" >> chuhan.txt
$ git add .
$ git commit -m "各路人馬起義反秦"
$ echo -n "先入咸陽者稱王,劉邦先入了咸陽" >> chuhan.txt
$ git add .
$ git commit -m "劉邦入咸陽"

$ 推送到遠(yuǎn)程
$ git push origin chuhan

6.刪除大文件

此時(shí)雅倒,要?jiǎng)h除大文件bigqin璃诀。

1.垃圾回收

先進(jìn)行垃圾回收,并壓縮一些文件

$ git gc --prune=now

Git最初向磁盤中存儲(chǔ)對(duì)象使用松散的格式蔑匣,后續(xù)會(huì)將多個(gè)對(duì)象打包為一個(gè)二進(jìn)制的包文件packfile)劣欢,以節(jié)省磁盤空間

.pack文件存儲(chǔ)了對(duì)象的內(nèi)容

.idx文件存儲(chǔ)了包文件偏移信息,用于`索引具體的對(duì)象

打包對(duì)象時(shí)裁良,查找命名和大小相近的文件氧秘,保留文件不同版本之間的差異最新一版保存完整內(nèi)容,訪問頻率最高)

2.查找大文件

使用git rev-list --objects —all顯示所有commit及其所關(guān)聯(lián)的所有對(duì)象

$ git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -3 | awk '{print$1}')"

e9461c55c3b8807351909cf7bb46eb22a8df5533 README.md
b866711af76e7d7cc87d9828f8ddde8ea865d053 bigqin
8d675f2ad83219ad4ebe34fe4dcac3a7139002ea bigqin

verify-pack -v *.idx:查看壓縮包內(nèi)容

3.刪除指定的大文件
$ git filter-branch --force --index-filter "git rm -rf --cached --ignore-unmatch bigqin" --prune-empty --tag-name-filter cat -- --all
Rewrite bf551acd0ca40a5671bcf2d4cad83a999b8baf52 (10/16) (0 seconds passed, remaining 0 predicted)    rm 'bigqin'
Rewrite d1d31551ecb36d362fd1051152f1fc886e4df95c (11/16) (0 seconds passed, remaining 0 predicted)    rm 'bigqin'
Rewrite da902adff9f3f890aa4c3304c5ac6d1e14f589da (12/16) (0 seconds passed, remaining 0 predicted)    rm 'bigqin'
Rewrite c96090316c3600e6e190cb9f99cf14a58f6f09ca (13/16) (0 seconds passed, remaining 0 predicted)    rm 'bigqin'
Rewrite 9d6c9194d76c5e0aa6c9119445681c9fbdf735a3 (14/16) (1 seconds passed, remaining 0 predicted)    rm 'bigqin'
Rewrite b1e2f243a559547e3a0f5eaa18f6a31a35eaa57a (14/16) (1 seconds passed, remaining 0 predicted)    rm 'bigqin'
Rewrite ac49fbb891648b73bbd31b4e82b56bbd71254384 (14/16) (1 seconds passed, remaining 0 predicted)    rm 'bigqin'
.....

filter-branch 命令通過一個(gè)filter來重寫歷史提交趴久,這個(gè)filter針對(duì)指定的所有分支(rev-list)運(yùn)行。

--index-filter:過濾Git倉(cāng)庫(kù)的index搔确,該過濾命令作用于git rm -rf --cached --ignore-unmatch bigqin彼棍。不checkoutworking directory,只修改index的文件膳算,速度快座硕。

--cached會(huì)刪除index中的文件

--ignore-unmatch:如果沒匹配到文件,不會(huì)報(bào)錯(cuò)涕蜂,會(huì)繼續(xù)執(zhí)行命令

最后一個(gè)參數(shù)file/directory是要被刪除的文件的名字

--prune-empty:指示git filter-branch 完全刪除所有的空commit华匾。

-–tag-name-filter:將每個(gè)tag指向重寫后的commit。

cat命令會(huì)在收到tag時(shí)返回tag名稱

–-選項(xiàng)用來分割 rev-list 和 filter-branch 選項(xiàng)

--all參數(shù)告訴Git我們需要重寫所有分支(或引用)机隙。

注意:git rm 這一行命令使用雙引號(hào)"git rm -rf --cached --ignore-unmatch bigqin"

4.刪除緩存

移除本地倉(cāng)庫(kù)中指向舊提交的剩余refs蜘拉,git for-each-ref 會(huì)打印倉(cāng)庫(kù)中匹配refs/original的所有refs,并使用delete作為前綴有鹿,此命令通過管道傳送到 git update-ref 命令旭旭,該命令會(huì)移除所有指向舊commit的引用。

$ git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin

以下命令會(huì)使reflog到期葱跋,因?yàn)樗廊话鴮?duì)舊commit的引用持寄。使用--expire=now 參數(shù),確保它在目前為止到期了娱俺。如果沒有該參數(shù)稍味,只會(huì)移除超過90天的reflog。

$ git reflog expire --expire=now --all

現(xiàn)在本地倉(cāng)庫(kù)依然包含著所有舊commit的對(duì)象荠卷,但已經(jīng)沒有引用指向它們了模庐,這些對(duì)象需要被刪除掉。此時(shí)可以使用 git gc 命令僵朗,Git的垃圾回收器會(huì)刪除這些沒有引用指向的對(duì)象赖欣。

$ git gc --prune=now

gc使用--prune 參數(shù)來清理特定時(shí)期的對(duì)象屑彻,默認(rèn)情況下為2周,指定now將刪除所有這些對(duì)象而沒有時(shí)期限制顶吮。

$ du -sh .git
104K    .git

此時(shí)社牲,.git文件的大小只有104k了。

7.提交重寫的歷史到遠(yuǎn)程

如果確認(rèn)所做的刪除大文件操作沒有問題悴了,就可以提交到遠(yuǎn)程倉(cāng)庫(kù)了搏恤,一旦提交,再也沒有辦法恢復(fù)到原來的狀態(tài)湃交,一定要小心謹(jǐn)慎熟空!一定要小心謹(jǐn)慎!一定要小心謹(jǐn)慎搞莺!

先進(jìn)行備份工作息罗,以免出現(xiàn)問題:

$ cd ~/Desktop/
$ mkdir gitthin_mirror && cd gitthin_mirror
$ git clone --mirror git@gitee.com:coderhony/gitthin.git

再回到剛才做的已經(jīng)瘦身的Git倉(cāng)庫(kù)

$ cd ~/Desktop/gitthin/gitthin

把已瘦身的倉(cāng)庫(kù)同步到遠(yuǎn)程倉(cāng)庫(kù),使用—mirror參數(shù):

$ git push --mirror git@gitee.com:coderhony/gitthin.git

為了確保都已同步才沧,再執(zhí)行以下命令:

$ git push --all --force
Everything up-to-date
$ git push --tags --force
Everything up-to-date

8.更新其他的clone

在過濾存儲(chǔ)庫(kù)迈喉,并重寫提交歷史后,將更改強(qiáng)制推送到遠(yuǎn)程服務(wù)器之后∥略玻現(xiàn)在要更新該存儲(chǔ)庫(kù)的每一份clone挨摸,僅靠常用的pull是無法做到這一點(diǎn)的。

第一步是從遠(yuǎn)程服務(wù)器獲取存儲(chǔ)庫(kù)岁歉,使用git reset 將存儲(chǔ)庫(kù)從 origin/master 切換到舊存儲(chǔ)庫(kù)狀態(tài)得运。

$ git fetch origin
$ git reset --hard origin/master

和上面的一樣,需要?jiǎng)h除舊提交锅移,清理本地倉(cāng)庫(kù)

$ git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
$ git reflog expire --expire=now --all
$ git gc --prune=now

參考資料:

Remove files from git history

Git++ - 倉(cāng)庫(kù)瘦身

git瘦身

尋找并刪除Git記錄中的大文件

為什么你的 Git 倉(cāng)庫(kù)變得如此臃腫

Maintaining a Git Repository

Removing sensitive data from a repository

如何瘦身 Git 倉(cāng)庫(kù)

記一次刪除Git記錄中的大文件的過程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末熔掺,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子帆啃,更是在濱河造成了極大的恐慌瞬女,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件努潘,死亡現(xiàn)場(chǎng)離奇詭異诽偷,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)疯坤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門报慕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人压怠,你說我怎么就攤上這事眠冈。” “怎么了蜗顽?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵布卡,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我雇盖,道長(zhǎng)忿等,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任崔挖,我火速辦了婚禮贸街,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘狸相。我一直安慰自己薛匪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布脓鹃。 她就那樣靜靜地躺著逸尖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瘸右。 梳的紋絲不亂的頭發(fā)上冷溶,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音尊浓,去河邊找鬼。 笑死纯衍,一個(gè)胖子當(dāng)著我的面吹牛栋齿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播襟诸,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瓦堵,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了歌亲?” 一聲冷哼從身側(cè)響起菇用,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎陷揪,沒想到半個(gè)月后惋鸥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡悍缠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年卦绣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片飞蚓。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡滤港,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出趴拧,到底是詐尸還是另有隱情溅漾,我是刑警寧澤山叮,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站添履,受9級(jí)特大地震影響屁倔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜缝龄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一汰现、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧叔壤,春花似錦瞎饲、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至俺亮,卻和暖如春驮捍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背脚曾。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工东且, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人本讥。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓珊泳,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親拷沸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子色查,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • Add & Commit git init 初始化一個(gè) Git 倉(cāng)庫(kù)(repository),即把當(dāng)前所在目錄變成...
    冬絮閱讀 4,831評(píng)論 0 9
  • 1. 安裝 Github 查看是否安裝git: $ git config --global user.name "...
    Albert_Sun閱讀 13,656評(píng)論 9 163
  • 1. GIT命令 git init在本地新建一個(gè)repo撞芍,進(jìn)入一個(gè)項(xiàng)目目錄秧了,執(zhí)行g(shù)it init,會(huì)初始化一個(gè)re...
    江邊一蓑煙閱讀 798評(píng)論 0 0
  • 2018年1月29日 網(wǎng)友的來信 春天老師序无,我是杭州的博友验毡,自從看了一篇新浪首頁(yè)推薦(這個(gè)推薦我還真不知道)的“贍...
    魅力春天閱讀 207評(píng)論 0 1
  • 亮亮的城市在太空中旋轉(zhuǎn) 可愛的水晶譜寫了歷史 感受到人生的美好 但也曾是你的生命的悲哀 寥落的星光散滿天空泛起芬芳...
    虎哥科幻工坊閱讀 214評(píng)論 3 3