81

(已解决,见问题正文底部)
找这个很久了,到现在我有的是:

几乎相同的方法,但它们都将对象留在包文件中......卡住了。
我尝试了什么:

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 :(

解决方案:这是摆脱文件的最短方法:

  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 - 检查最大的文件
  3. (可选) 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- 最终移除这些对象
4

8 回答 8

67

如果无法访问您的存储库数据,我不能肯定地说,但我相信可能有一个或多个打包的 refs 仍在引用您运行之前的旧提交git filter-branch。这可以解释为什么git fsck --full --unreachable不将大 blob 称为无法访问的对象,即使您已过期 reflog 并删除了原始(未打包的)refs。

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

1)确保原始参考消失:

rm -rf .git/refs/original

2) 使所有 reflog 条目过期:

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

3)检查旧的打包参考

这可能会很棘手,具体取决于您拥有多少打包参考。我不知道任何可以自动执行此操作的 Git 命令,因此我认为您必须手动执行此操作。备份.git/packed-refs. 现在编辑.git/packed-refs. 检查旧的参考(特别是,看看它是否包含来自 的任何参考.git/refs/original)。如果您发现任何不需要的旧的,请删除它们(删除该引用的行)。

清理完packed-refs文件后,看看是否git fsck注意到无法访问的对象:

git fsck --full --unreachable

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

4) 重新打包打包好的档案

git repack -A -d

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

5)修剪松散(无法到达)的对象

git prune

那应该这样做。Git 确实应该有更好的方法来管理打包的引用。也许有更好的方法,我不知道。在没有更好的方法的情况下,手动编辑packed-refs文件可能是唯一的方法。

于 2010-02-01T20:01:13.980 回答
15

我建议使用BFG Repo-Cleaner,这是一种更简单、更快的替代方案,git-filter-branch专门用于从 Git 历史中重写文件。它使您的生活在这里变得更轻松的一种方法是,它实际上默认处理所有引用(所有标签、分支、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(不在您的最新提交中)的文件都将从您的存储库的历史记录中完全删除。然后,您可以使用git gc清除死数据:

$ git gc --prune=now --aggressive

BFG 通常比使用简单得多git-filter-branch- 选项是围绕这两个常见用例定制的:

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

全面披露:我是 BFG Repo-Cleaner 的作者。

于 2013-04-02T18:00:51.197 回答
6

我发现这对于删除整个文件夹非常有帮助,因为上述内容并没有真正帮助我: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
于 2013-03-20T14:27:01.183 回答
5

我试图摆脱历史上的一个大文件,上面的答案在一定程度上是有效的。关键是:如果你有标签,它们就不起作用。如果可以从标签访问包含大文件的提交,那么您需要调整 filter-branches 命令:

git filter-branch --tag-name-filter cat \
--index-filter 'git rm --cached --ignore-unmatch huge_file_name' -- \
--all --tags
于 2012-04-19T09:07:13.540 回答
3

这应该包含git obliterate在 Git Extras ( https://github.com/visionmedia/git-extras ) 中的命令中。

git obliterate <filename>
于 2013-03-25T20:25:49.283 回答
2

之后仍然有很大的 git repo 大小有各种原因git gc,因为它不会删除所有松散的对象

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

但是在您的情况下测试的一个技巧是克隆您的“清理过的”Git repo并查看克隆是否具有适当的大小。

('“清理”回购'是您应用filter-branch, 然后gcand的地方prune

于 2010-02-01T05:04:21.150 回答
2

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

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

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

然后,要从存储库中取出所有松散的对象:

git gc --prune='0 days ago'
于 2010-01-29T20:57:12.803 回答
1

I had the same problem and I found a great tutorial on github that explain step by step how to get rid of files you accidentally committed.

Here is a little summary of the procedure as Cupcake suggested.

If you have a file named file_to_remove to remove from the history :

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
于 2013-03-12T12:02:21.327 回答