从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:这是摆脱文件的最短途径:
- 检查.git / packed-refs – 我的问题是,我有一个远程存储库的
refs/remotes/origin/master
行,删除它,否则git不会删除这些文件 - (可选)
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
– 检查最大的文件 - (可选)
git rev-list --objects --all | grep a0d770a97ff0fac0be1d777b32cc67fe69eb9a98
git rev-list --objects --all | grep a0d770a97ff0fac0be1d777b32cc67fe69eb9a98
– 检查这些文件是什么 -
git filter-branch --index-filter 'git rm --cached --ignore-unmatch file_names'
– 从所有版本中删除一个文件 -
rm -rf .git/refs/original/
– 删除git的备份 -
git reflog expire --all --expire='0 days'
– 将所有松散的对象过期 -
git fsck --full --unreachable
– 检查是否有任何松散的对象 -
git repack -A -d
– 重新打包 -
git prune
– 最后删除这些对象
我不能确定没有访问您的存储库数据,但我相信可能有一个或多个打包引用仍然引用旧提交之前运行git filter-branch
。 这可以解释为什么git fsck --full --unreachable
不会调用大的blob不可访问的对象,即使你已经过期了你的reflog,并删除了原始的(unpacked)裁判。
下面是我要做的(在git filter-branch
和git 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
,然后是gc
和prune
)
这应该由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