Git:如何从历史提交中删除文件?


113

我已提交ID为56f06019的提交(例如)。在该提交中,我意外地提交了大文件(50Mb)。在另一次提交中,我添加了相同的文件,但大小合适(小)。现在,当我克隆的文件太重时,我的存储库:(如何从存储库历史记录中删除该大文件以减小存储库的大小?


就我而言,它不是一个大文件,而是一个包含数据库信用的配置文件。我当时正在学习git,那时我还没有意识到.gitignore。
拉希


Answers:


165

Pro Git书的第9章中有一节“ 删除对象”

让我在这里简要概述一下步骤:

git filter-branch --index-filter \
    'git rm --cached --ignore-unmatch path/to/mylarge_50mb_file' \
    --tag-name-filter cat -- --all

就像前面描述的重新定标选项一样,它filter-branch是重写操作。如果您已发布历史记录,则必须--force推送新的参考。

filter-branch方法比该rebase方法强大得多,因为它可以

  • 允许您一次处理所有分支/引用,
  • 动态重命名所有标签
  • 自添加文件以来,即使已经进行了几次合并提交,也可以正常运行
  • 即使在(a)个分支的历史记录中多次(重新)添加/删除了文件,文件也可以正常运行
  • 不会创建新的,不相关的提交,而是在修改与之关联的树时将其复制。这意味着将保留诸如已签名的提交,提交注释等内容。

filter-branch 也保留备份,因此除非您使reflog和垃圾回收到期,否则仓库的大小不会立即减小:

rm -Rf .git/refs/original       # careful
git gc --aggressive --prune=now # danger

1
值得注意的是,这在Windows cmd.exe下似乎不起作用。似乎可以在cygwin下正常工作。
假名称

2
我通过使用双引号而不是单引号使上面的git filter-branch起作用(在Windows Server 2012 cmd.exe上)
JCii 2013年

1
对我有用的是此筛选器分支命令行。 git filter-branch --force --index-filter 'git rm --ignore-unmatch --cached PathTo/MyFile/ToRemove.dll' -- fbf28b005^.. 然后rm --recursive --force .git/refs/originalrm --recursive --force .git/logs 然后我使用git prune --expire nowgit gc --aggressive 这对我来说比上面列出的确切步骤更好。感谢您包含指向Git Pro书籍的链接,因为它非常宝贵。
dacke.geo

在执行filter-branch命令之后,我可以减小.git文件夹大小的唯一方法是遵循此处找到的命令:stackoverflow.com/questions/1904860/…git -c gc.reflogExpire = 0 -c gc。 reflogExpireUnreachable = 0 -c gc.rerereresolved = 0 \ -c gc.rerereunresolved = 0 -c gc.pruneExpire = now gc“ $ @”
史蒂夫·阿迪斯

对于收缩回购,我用在GIT中滤波器分支文档列出的命令:git-scm.com/docs/...
朱利Ronsin


0

您将需要在交互模式下进行git rebase,请参见此处的示例:如何在GitHub上删除提交?以及如何删除旧提交

如果您的提交为HEAD减去10次提交:

$ git rebase -i HEAD~10

在发布历史记录之后,您需要推送“新”历史记录,需要添加+强制(请参见push选项中的refspec ):

$ git push origin +master

如果其他人已经克隆了您的存储库,您将通知他们,因为您只是更改了历史记录。


3
这并没有从历史中删除大文件。同样,强制推送的规范方法是git push --forcegit push -f(不需要人们知道分支推送的目标)
sehe 2012年

基于该问题,新文件与旧文件完全相同,即相同的路径。这就是为什么您不能直接git rm在路径上使用的原因。
安特罗什(Loïcd'Anterroches),2012年

2
@sehe,如果您进行了重新设置以消除具有大文件的提交,那么它就一去不复返了。
vonbrand

@vonbrand仅来自您重新定标的那个分支。我不认为'from'分支会被删除。但是,是的,如果您删除修订版本树分支,这将有所帮助:_
sehe 2013年

@sehe,当然,您必须跟踪包含违规提交的所有分支。如果是在回购中有些疲倦之前,您将需要进行大量重组。但是rebase 实现此目的的工具。
vonbrand


0

您可以使用简单的命令删除

 git rm -r -f app/unused.txt 
 git rm -r -f yourfilepath
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.