从git存储库中删除文件(历史logging)

(解决,请参阅问题主体的底部)
现在找这个已经很久了,到现在为止是这样的:

  • http://dound.com/2009/04/git-forever-remove-files-or-folders-from-history/和
  • http://progit.org/book/ch9-7.html

几乎相同的方法,但他们都留在包文件中的对象…卡住了。
我试过的:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch file_name' rm -Rf .git/refs/original rm -Rf .git/logs/ git gc 

仍然有包中的文件,这是我知道的:

 git verify-pack -v .git/objects/pack/pack-3f8c0...bb.idx | sort -k 3 -n | tail -3 

和这个:

 git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch file_name" HEAD rm -rf .git/refs/original/ && git reflog expire --all && git gc --aggressive --prune 

一样…

尝试git clone技巧,它删除了一些文件(约3000人),但最大的文件仍然存在…

我有一些在存储库中的大型遗留文件,〜200M,我真的不希望他们在那里…而我不想重置存储库为0 🙁

解决scheme:这是摆脱文件的最短途径:

  1. 检查.git / packed-refs – 我的问题是,我有一个远程存储库的refs/remotes/origin/master行,删除它,否则git不会删除这些文件
  2. (可选) git verify-pack -v .git/objects/pack/#{pack-name}.idx | sort -k 3 -n | tail -5 git verify-pack -v .git/objects/pack/#{pack-name}.idx | sort -k 3 -n | tail -5 git verify-pack -v .git/objects/pack/#{pack-name}.idx | sort -k 3 -n | tail -5 – 检查最大的文件
  3. (可选) git rev-list --objects --all | grep a0d770a97ff0fac0be1d777b32cc67fe69eb9a98 git rev-list --objects --all | grep a0d770a97ff0fac0be1d777b32cc67fe69eb9a98 – 检查这些文件是什么
  4. git filter-branch --index-filter 'git rm --cached --ignore-unmatch file_names' – 从所有版本中删除一个文件
  5. rm -rf .git/refs/original/ – 删除git的备份
  6. git reflog expire --all --expire='0 days' – 将所有松散的对象过期
  7. git fsck --full --unreachable – 检查是否有任何松散的对象
  8. git repack -A -d – 重新打包
  9. git prune – 最后删除这些对象

我不能确定没有访问您的存储库数据,但我相信可能有一个或多个打包引用仍然引用旧提交之前运行git filter-branch 。 这可以解释为什么git fsck --full --unreachable不会调用大的blob不可访问的对象,即使你已经过期了你的reflog,并删除了原始的(unpacked)裁判。

下面是我要做的(在git filter-branchgit gc完成之后):

1)确保原始参考文件不存在:

rm -rf .git/refs/original

2)过期所有reflog条目:

git reflog expire --all --expire='0 days'

3)检查旧包装文件

这可能是棘手的,取决于你有多less打包裁判。 我不知道任何自动执行此操作的Git命令,因此我认为您必须手动执行此操作。 做一个.git/packed-refs的备份。 现在编辑.git/packed-refs 。 检查旧的refs(特别是,看它是否打包.git/refs/original任何.git/refs/original )。 如果您发现任何不需要在那里的旧的,删除它们(删除该参考线)。

清理packed-refs文件之后,看看git fsck注意到不可访问的对象:

git fsck --full --unreachable

如果这有效,并且git fsck现在将您的大块报告为无法访问,则可以继续下一步。

4)重新打包打包的文档

git repack -A -d

这将确保无法访问的对象解压缩并保持解压缩状态。

5)修剪松散(无法到达)的物体

git prune

这应该做到这一点。 Git真的应该有一个更好的方式来pipe理打包裁判。 也许有一个我不知道的更好的方法。 在没有更好的方法的情况下,手动编辑packed-refs文件可能是唯一的方法。

我build议使用BFG Repo-Cleaner ,这个更简单,更快的替代git-filter-branch专门用于重写Git历史logging的文件。 让你的生活更轻松的一个方法就是它实际上默认处理所有的引用(所有标签,分支,像refs / remotes / origin / master等),但速度也快了10-50倍。

你应该仔细地按照这些步骤: http : //rtyley.github.com/bfg-repo-cleaner/#usage – 但核心是这样的:下载BFG的jar (需要Java 6或以上),并运行此命令:

 $ java -jar bfg.jar --delete-files file_name my-repo.git 

任何名为file_name文件(不在你最近的提交中)将被完全从你的版本库的历史logging中删除 。 然后你可以使用git gc清理死亡数据:

 $ git gc --prune=now --aggressive 

BFG通常比git-filter-branch更简单 – 这些选项是围绕这两个常见的用例来定制的:

  • 删除疯狂的大文件
  • 删除密码,证件和其他私人数据

充分披露:我是BFG Repo-Cleaner的作者。

我发现这是相当有益的删除整个文件夹,因为上述并没有真正帮助我: https : //help.github.com/articles/remove-sensitive-data 。

我用了:

 git filter-branch -f --force \ --index-filter 'git rm -rf --cached --ignore-unmatch folder/sub-folder' \ --prune-empty --tag-name-filter cat -- --all rm -rf .git/refs/original/ git reflog expire --expire=now --all git gc --prune=now git gc --aggressive --prune=now 

我试图摆脱历史上的一个大文件,上面的答案奏效了。 重点是:如果你有标签,他们不会工作。 如果包含大文件的提交可以从标签到达,那么您需要调整filter-branches命令:

 git filter-branch --tag-name-filter cat \ --index-filter 'git rm --cached --ignore-unmatch huge_file_name' -- \ --all --tags 

请参阅: 如何从git的历史logging中删除敏感文件

如果该文件不存在于rev中,则上述操作将失败。 在这种情况下,'–ignore-unmatch'开关将修复它:

 git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch <filename>' HEAD 

然后,把所有松散的物体拿出来:

 git gc --prune='0 days ago' 

git gc ,你有各种各样的理由git repo大小,因为它不会删除所有松散的对象 。

我在“ 减lessgit存储库大小 ”中详细说明了这些原因

但在你的情况下testing的一个窍门是克隆你的“清理”的Git仓库 ,看看克隆是否有适当的大小。

('清理'repo'就是你应用filter-branch ,然后是gcprune

这应该由Git Extras( https://github.com/visionmedia/git-extras )中的git obliterate命令覆盖。

 git obliterate <filename> 

我遇到了同样的问题,我在github上find了一个很好的教程 ,一步一步地解释如何摆脱不小心犯的文件。

这是杯形蛋糕build议的程序的一个小结。

如果您有一个名为file_to_remove的文件从历史logging中删除:

 cd path_to_parent_dir git filter-branch --force --index-filter \ 'git rm --cached --ignore-unmatch file_to_remove' \ --prune-empty --tag-name-filter cat -- --all