我不小心把一个dvd光盘放到了一个网站项目中,然后不小心提交-a -m…而且,快,回购膨胀了2.2 g。下次我做了一些编辑,删除了视频文件,并提交了所有内容,但压缩文件仍然在存储库中,在历史中。

我知道我可以从这些提交中启动分支,并将一个分支重置到另一个分支上。但是我应该怎么做才能合并两次提交,使大文件不显示在历史记录中,并在垃圾收集过程中被清理?


当前回答

除了git filter-branch(缓慢但纯粹的git解决方案)和BFG(更简单,性能非常好)之外,还有另一个性能良好的过滤工具:

https://github.com/xoofx/git-rocket-filter

从它的描述来看:

git-rocket-filter的目的类似于git-filter-branch命令,但提供了以下独特的功能:

快速重写提交和树(从x10到x100的顺序)。 内置支持使用——keep(保存文件或目录)的白名单和使用——remove选项的黑名单。 使用.gitignore类似的模式进行树过滤 快速和简单的c#脚本提交过滤和树过滤 支持每个文件/目录模式的树过滤脚本 自动修剪空的/不变的提交,包括合并提交

其他回答

Git filter-branch是一个功能强大的命令,你可以使用它从提交历史中删除一个巨大的文件。该文件将保留一段时间,Git将在下一次垃圾收集中删除它。 下面是从提交历史中删除文件的完整过程。为了安全起见,下面的进程首先在一个新分支上运行命令。如果结果是您所需要的,那么将其重置回您实际想要更改的分支。

# Do it in a new testing branch
$ git checkout -b test

# Remove file-name from every commit on the new branch
# --index-filter, rewrite index without checking out
# --cached, remove it from index but not include working tree
# --ignore-unmatch, ignore if files to be removed are absent in a commit
# HEAD, execute the specified command for each commit reached from HEAD by parent link
$ git filter-branch --index-filter 'git rm --cached --ignore-unmatch file-name' HEAD

# The output is OK, reset it to the prior branch master
$ git checkout master
$ git reset --soft test

# Remove test branch
$ git branch -d test

# Push it with force
$ git push --force origin master

新的答案在20222年有效。

请勿使用:

git filter-branch

此命令可能不会在按下后更改远程回购。如果你在使用它后进行克隆,你会看到什么都没有改变,回购仍然有一个很大的大小。这个命令现在已经过时了。例如,如果您使用https://github.com/18F/C2/issues/439中的步骤,这将不起作用。

你需要使用

git filter-repo

步骤:

(1)找到。git中最大的文件:

git rev-list --objects --all | grep -f <(git verify-pack -v  .git/objects/pack/*.idx| sort -k 3 -n | cut -f 1 -d " " | tail -10)

(2)开始过滤这些大文件:

 git filter-repo --path-glob '../../src/../..' --invert-paths --force

or

 git filter-repo --path-glob '*.zip' --invert-paths --force

or

 git filter-repo --path-glob '*.a' --invert-paths --force

或 无论你在第一步中找到什么。

(3)

 git remote add origin git@github.com:.../...git

(4)

git push --all --force

git push --tags --force

完成了! !

为什么不使用这个简单而强大的命令呢?

git filter-branch --tree-filter 'rm -f DVD-rip' HEAD

——tree-filter选项在项目每次签出后运行指定的命令,然后重新提交结果。在这种情况下,您从每个快照中删除一个名为DVD-rip的文件,无论它是否存在。

如果你知道是哪个提交引入了这个巨大的文件(比如35dsa2),你可以用35dsa2替换HEAD。HEAD以避免重写太多的历史,从而避免在还没有推送的情况下出现不同的提交。@alpha_989提供的这个评论似乎太重要了,不能在这里省略。

请看这个链接。

在尝试了SO中的几乎所有答案后,我终于找到了这个gem,它可以快速删除我的存储库中的大文件,并允许我再次同步:http://www.zyxware.com/articles/4027/how-to-delete-files-permanently-from-your-local-and-remote-git-repositories

CD到本地工作文件夹,执行以下命令:

git filter-branch -f --index-filter "git rm -rf --cached --ignore-unmatch FOLDERNAME" -- --all

将FOLDERNAME替换为你想从给定的git存储库中删除的文件或文件夹。

一旦完成,运行以下命令清理本地存储库:

rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now
git gc --aggressive --prune=now

现在将所有更改推到远程存储库:

git push --all --force

这将清理远程存储库。

使用BFG Repo-Cleaner,这是一个更简单、更快的Git -filter-branch的替代方案,专门用于从Git历史记录中删除不需要的文件。

仔细按照使用说明,核心部分就是这样:

$ java -jar bfg.jar --strip-blobs-bigger-than 100M my-repo.git

任何超过100MB大小的文件(不是最近提交的文件)都将从Git存储库的历史记录中删除。然后你可以使用git gc清除死数据:

$ git reflog expire --expire=now --all && git gc --prune=now --aggressive

修剪后,我们可以强制推送到远程repo*

$ git push --force

*注意:不能在GitHub上强制推送一个保护分支

BFG通常比运行git-filter-branch快10-50倍,而且通常更容易使用。

完全披露:我是好心眼巨人回收清理器的作者。