折叠一个git存储库的历史

我们有一个有很大历史的git项目。

具体来说,在项目的早期,项目中有相当多的二进制资源文件,现在已经被删除,因为它们是有效的外部资源。

但是,由于之前提交了这些文件,因此我们的存储库的大小大于200MB(总计结算大约为20MB)。

我们想要做的是“折叠”历史logging,以便版本库看起来是从以后的版本创build的。 例如

1-----2-----3-----4-----+---+---+ \ / +-----+---+---+ 
  1. 创build了存储库
  2. 大量的二进制文件添加
  3. 大量的二进制文件被删除
  4. 存储库的新的“开始”

所以我们有效的想要在某个点之前失去项目历史。 在这一点上,只有一个分支,所以没有复杂的处理多个起点等。但是我们不想失去所有的历史,并开始与当前版本的新库。

这是可能的,还是我们注定永远有一个臃肿的存储库?

您可以删除二进制文件,并保留其余的历史logging。 Git允许你在提交之前重新sorting和“挤压”,所以你可以只提交添加和删除你的大的二进制文件的提交。 如果这些添加全部在一个提交中完成,而在另一个提交中完成,那么这比处理每个文件要容易得多。

 $ git log --stat # list all commits and commit messages 

search这个提交,添加和删除你的二进制文件,并记下他们的SHA1,比如2bcdef3cdef3

然后编辑回购的历史logging,使用rebase -i命令及其交互选项,从添加二进制文件的提交的父节点开始。 它会启动你的$ EDITOR,你会看到一个以2bcdef开始的提交列表:

 $ git rebase -i 2bcdef^ # generate a pick list of all commits starting with 2bcdef # Rebasing zzzzzz onto yyyyyyy # # Commands: # pick = use commit # edit = use commit, but stop for amending # squash = use commit, but meld into previous commit # # If you remove a line here THAT COMMIT WILL BE LOST. # pick 2bcdef Add binary files and other edits pick xxxxxx Another change . . pick 3cdef3 Remove binary files; link to them as external resources . . 

插入squash 3cdef3作为第二行,并删除从列表中pick 3cdef3的行。 你现在有了一个交互式rebase的动作列表,它将提交的内容添加和删除你的二进制文件合并为一个提交,其差异就是这些提交中的任何其他更改。 然后,当你告诉它完成时,它将重新应用所有后续的提交:

 $ git rebase --continue 

这将需要一两分钟的时间。
你现在有一个回购,不再有二进制文件来来去去。 但是他们仍然会占用一些空间,因为默认情况下,Git保持30天左右的变化才能被垃圾回收,这样你就可以改变主意了。 如果你想现在删除它们:

 $ git reflog expire --expire=1.minute refs/heads/master #all deletions up to 1 minute ago available to be garbage-collected $ git fsck --unreachable # lists all the blobs(files) that will be garbage-collected $ git prune $ git gc 

现在你已经消除了膨胀,但保留了你的历史的其余部分。

你可以使用git filter-branch和grafts来使提交号码4成为你的分支的新的根提交。 只需创build文件.git/info/grafts其中只有一行包含提交编号为4的SHA1。

如果你现在做一个git loggitk你会看到这些命令将显示提交号码4作为你的分支的根。 但是在你的仓库里没有任何东西会改变。 你可以删除.git/info/graftsgit loggitk的输出将和以前一样。 要实际提交数字4新的根你将不得不运行git filter-branch ,没有参数。

感谢JesperE的post,我看着git-filter-branch – 这实际上可能是你想要的。 看起来你可以保留你以前的提交,除非你的大文件被删除后才会被修改。 从git-filter-branch手册页 :

假设您想从所有提交中删除文件(包含机密信息或版权侵犯):

git filter-branch –tree-filter'rm filename'HEAD

一定要阅读该手册页…显然你想要在你的仓库的备用克隆上做到这一点,以确保它按预期工作。

git-fast-export你正在寻找什么?

 NAME git-fast-export - Git data exporter SYNOPSIS git-fast-export [options] | git-fast-import DESCRIPTION This program dumps the given revisions in a form suitable to be piped into git-fast- import(1). You can use it as a human readable bundle replacement (see git-bundle(1)), or as a kind of an interactive git-filter-branch(1).