2012-08-13 138 views
19

我有一個非常大的Git倉庫,其中只包含經常更改的二進制文件。當然,Git存儲庫是,比其中的實際文件大很多。我並不關心舊的歷史,我只需要一些新的歷史就能夠回覆一些錯誤的變化。假設我想刪除除最後五個提交之外的所有提交。如何刪除除最後五個之外的所有Git提交

當然,我想這樣做是爲了讓存儲庫保持較小的狀態,以便刪除的提交必須從存儲庫中徹底清除。

我想用單個命令(別名)或腳本非交互式地完成所有這些。我怎樣才能做到這一點?

+2

這可能幫助: http://stackoverflow.com/questions/250238/collapsing-a-git-repositorys-history – 2012-08-13 07:33:29

+3

您確定要_remove_所有舊的提交?這意味着也要消除他們的變化。 GIT不會在每次提交中存儲「當前狀態」,它僅存儲更改。你想要做的是將所有舊的提交壓縮成一個,不是嗎? – amorfis 2012-08-13 09:21:28

回答

8

這裏是一個rebase-last-five別名,以幫助您入門。它將重新創建當前分支,因此只有最近的五個提交都在歷史中。最好將這個腳本(git-rebase-last-five.sh)放在PATH的目錄中; Git將查找並使用名爲git-....sh的腳本,而無需任何特殊配置。腳本應該比這個簡單的別名做更多的錯誤檢查和處理。

$ git config --global alias.rebase-last-five '!b="$(git branch --no-color | cut -c3-)" ; h="$(git rev-parse $b)" ; echo "Current branch: $b $h" ; c="$(git rev-parse $b~4)" ; echo "Recreating $b branch with initial commit $c ..." ; git checkout --orphan new-start $c ; git commit -C $c ; git rebase --onto new-start $c $b ; git branch -d new-start ; git gc' 

買者自負:不要聽從warnings about changing history

檢查man頁面(git help <command>online)以獲取更多信息。

使用示例:

$ git --version 
git version 1.7.12.rc2.16.g034161a 
$ git log --all --graph --decorate --oneline 
* e4b2337 (HEAD, master) 9 
* e508980 8 
* 01927dd 7 
* 75c0fdb 6 
* 20edb42 5 
* 1260648 4 
* b3d6cc8 3 
* 187a0ef 2 
* e5d09cf 1 
* 07bf1e2 initial 
$ git rebase-last-five 
Current branch: master e4b2337ef33d446bbb48cbc86b44afc964ba0712 
Recreating master branch with initial commit 20edb42a06ae987463016e7f2c08e9df10fd94a0 ... 
Switched to a new branch 'new-start' 
[new-start (root-commit) 06ed4d5] 5 
1 file changed, 1 insertion(+) 
create mode 100644 A 
First, rewinding head to replay your work on top of it... 
Applying: 6 
Applying: 7 
Applying: 8 
Applying: 9 
Deleted branch new-start (was 06ed4d5). 
Counting objects: 35, done. 
Delta compression using up to 2 threads. 
Compressing objects: 100% (15/15), done. 
Writing objects: 100% (35/35), done. 
Total 35 (delta 4), reused 0 (delta 0) 
$ git log --all --graph --decorate --oneline 
* a7fb54b (HEAD, master) 9 
* 413e5b0 8 
* 638a1ae 7 
* 9949c28 6 
* 06ed4d5 5 
+3

很棒!謝謝!但不是隻使用'git gc',我必須使用'git reflog expire --expire = now --all; git gc --prune = now'實際上使存儲庫更小。 – kayahr 2012-08-17 15:52:43

+0

@ kayahr很高興爲您提供幫助。感謝您分享實際爲您工作的更改。 – 2012-08-17 18:12:16

+0

非常感謝,它的工作原理。你應該在你的答案中將腳本分解成幾行。我個人更喜歡在執行外部腳本之前理解我在做什麼。 – JulienD 2016-07-14 14:13:31

8

好吧,如果你想要什麼,我想你想(見我的意見),我認爲這應該工作:

  1. 創建分支保存所有提交(以防萬一):

    git branch fullhistory

  2. 雖然仍然在主復位 - 硬到你想從保留歷史記錄的提交:

    git reset --hard HEAD~5

  3. 現在重置但沒有--hard到歷史的開始,這應該離開你的工作空間不變,所以它仍然在HEAD〜5狀態。

    git reset --soft <first_commit>

  4. 所以,現在你有master空的歷史,你在工作區需要各方面的變化。只要提交它們。

    git commit -m "all the old changes squashed"

  5. 現在櫻桃採摘從fullhistory這4個提交你想在這裏:

    git cherry-pick A..B

其中A比B年紀了,還記得不包括在內。所以它應該是您想要包含的最舊提交的父代。