2012-03-19 39 views
2

可能重複:
Completely remove (old) git commits from history從git倉庫中取出最古老提交

Git是爲客戶網站每日快照是非常有用的。知道一切(php + mysqldump +用戶文件上傳)在git存儲庫中提供了極大的安心。

由於某些站點的大小很大,我想知道是否有人知道一個比較簡單的方法來刪除(例如)超過30天的所有提交?

+5

我不認爲Git真的是要用作備份解決方案,因此這並不是真正的意圖。你可能可以用rebase刪除它們,但我不知道如何以編程方式來完成。 – 2012-03-19 05:46:02

+0

關於「git沒有用於備份解決方案」,我想我們都同意這是真的。 (:但是從純粹務實的角度來講,我自己(並根據谷歌)許多其他人認爲它是一個非常適合備份解決方案 – Jacob 2012-03-19 06:23:51

+0

@JohnDouthat尼斯斑點!它不是立即明確,他們是重複的「問題」是不同的,但結果是一樣的。 – Jacob 2012-03-19 06:27:17

回答

3

確實,你其實可以做到這一點。這有點棘手。下面是一個例子...

$ cd /tmp 
$ mkdir rmcommits 
$ cd rmcommits 
$ git init 
Initialized empty Git repository in /tmp/rmcommits/.git/ 
$ cp /tmp/example/xy.c . 
$ git add xy.c 
$ git commit -m 'initial commit' 
[master (root-commit) 8d5b88c] initial commit 
1 files changed, 273 insertions(+), 0 deletions(-) 
create mode 100644 xy.c 
$ echo 'more stuff' > morestuff.txt 
$ git add morestuff.txt; git commit -m 'add some stuff' 
[master f971ae5] add some stuff 
1 files changed, 1 insertions(+), 0 deletions(-) 
create mode 100644 morestuff.txt 
$ echo 'and still more' >> morestuff.txt 
$ git add morestuff.txt; git commit -m 'add more stuff' 
[master bea9192] add more stuff 
1 files changed, 1 insertions(+), 0 deletions(-) 

現在我挑出來,我想「的歷史結束」的地方(分支主,又名HEAD):

$ git rev-parse HEAD^ 
f971ae5b4225aca364223a44be8be84268385ff3 

這是最後一次提交我會保持。

$ git filter-branch --parent-filter 'test $GIT_COMMIT == f971ae5b4225aca364223a44be8be84268385ff3 && echo "" || cat' HEAD 
Rewrite bea9192a53a5aeb7532aa1e174f7f642363396de (3/3) 
Ref 'refs/heads/master' was rewritten 
$ git log --pretty=oneline 
65a246b8320382a64550d2c4b650c942d7bfba70 add more stuff 
7892ab45aa33cd5ebdc3090ce2622081059fdd79 add some stuff 

(說明:git filter-branch基本上運行在分支的所有提交,在這種情況下master因爲HEAD目前ref: refs/heads/master,並與--parent過濾器,你可以重寫父(或多個)的每一個承諾當我們發現目標提交時,在我們希望歷史停止之前,我們什麼都不會迴應 - 你不需要空字符串,這是我的舊習慣,當沒有參數的迴應沒有做任何事情時 - 否則我們使用「貓」來複制現有的-p參數,按照過濾器分支手冊,這使得基於我們測試的那個新的提交沒有父母,即它現在是一個初始提交 - 分支的根。這是不尋常的在一個git倉庫中,因爲我們現在有兩個根提交,一個是新的master和一個在舊的,保存的主,如下所述。)

注意舊提交樹仍處於全部回購,所保存的名義是git filter-branch用途:

$ git log original/refs/heads/master --pretty=oneline 
bea9192a53a5aeb7532aa1e174f7f642363396de add more stuff 
f971ae5b4225aca364223a44be8be84268385ff3 add some stuff 
8d5b88c468f75750d5a01ab40bfae160c654ac66 initial commit 

你必須刪除引用(和清理掉引用日誌),做一個「混帳氣相色譜法」的改寫提交前(和任何未引用的樹,斑點等)真的走了:

$ git update-ref -d refs/original/refs/heads/master 
$ git reflog expire --expire=now --all 
$ git gc --prune=now 
$ git fsck --unreachable 
$ 

最後一行顯示,他們真的走了。

0
  1. 目前在庫的當前狀態的文件保存爲原始添加的文件加上了一系列的變化,所以你不能刪除提交其中的文件被添加。

  2. TortoiseGit有你來自哪裏,在日誌中選擇幾個連續的提交和「合併到一個犯」的操作,但它不是本地Git中提出,從我能從中出現的窗口推斷,實現爲創建一個新的分支,應用來自原始分支的更改,僅提交一次並重新分配結果。當選擇很多提交時,這當然不是一個快速操作,我想在大型存儲庫中它會更慢,並且在使用它之前我總是有一個備份。

總而言之,我懷疑存在一個簡單的方法來做到這一點。

+1

1:實際上,沒有,它不是。* packs *是壓縮的,所以你可以像deltas一樣節省空間,但是每個文件都是完整存儲的.git「commit」對象指向一個git「tree」對象,而「樹「對象列表」blob「(文件)和更多」樹「,全部通過SHA1 ID;並且從SHA1 ID,你提取文件批發(通過這些包的魔力)。 2.在原生git中,這是'git rebase --interactive'中的「squash」。是的,在它下面建立一個新的分支。 – torek 2012-03-20 08:26:17

+0

我站好了。在閱讀有關git內部結構時,我需要深入閱讀我瀏覽的章節。 – madth3 2012-03-22 20:43:07

+0

Git的壓縮技術是不尋常的,至少可以說。 :-)雖然非常有效。包做增量壓縮,但對象本身只是zlib壓縮的,並且在整個範圍內都有校驗和(在v2包中比v1更好)。壓縮算法以不同的方式被重複使用,以獲得用於拉和推操作的增量壓縮,但是這些壓縮算法在接收端被撤消。 – torek 2012-03-22 20:47:13