2012-03-19 75 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