【问题标题】:Remove file from git repository (history)从 git 存储库中删除文件(历史记录)
【发布时间】:2019-03-17 17:48:17
【问题描述】:

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

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

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 - 最终移除这些对象

【问题讨论】:

  • zneak - 我的问题在标题中。 gbacon - 尝试了这些,文件仍然保留在包文件中......
  • 如果您查看重复文件中引用的文章,它会显示如何在删除有问题的文件后压缩您的对象存储。
  • 这是救命稻草。心理提示:始终将潜在的巨大 *.log 文件添加到 .gitignore。在此之后从 800mb 的 repo 变成了 6mb。
  • 第二步和第三步合二为一for i in `git verify-pack -v .git/objects/pack/#{pack-name}.idx | sort -k 3 -n | tail -5` ; do git rev-list --objects --all | grep $(echo $i | sed 's/ .*//g') ; done

标签: git version-control git-rewrite-history


【解决方案1】:

我遇到了同样的问题,我在 github 上找到了一个很棒的 tutorial,它逐步解释了如何删除您意外提交的文件。

这里是 Cupcake 建议的程序的一个小总结。

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

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

【讨论】:

  • 在 Stack Overflow 上非常不鼓励仅链接的答案,因为如果将来链接断开,那么答案将变得毫无用处。请考虑在您的答案中总结链接中包含的相关信息。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    我发现这对于删除整个文件夹很有帮助,因为上述内容并没有真正帮助我: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
    

    【讨论】:

      【解决方案4】:

      我建议使用BFG Repo-Cleaner,它是git-filter-branch 的更简单、更快速的替代方案,专为重写 Git 历史文件而设计。它使您的生活在这里变得更轻松的一种方法是它实际上默认处理 all 引用(所有标签、分支、像 refs/remotes/origin/master 之类的东西),但它也是 10-50x更快。

      您应该在这里仔细按照以下步骤操作:http://rtyley.github.com/bfg-repo-cleaner/#usage - 但核心位是这样的:下载BFG's 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 的作者。

      【讨论】:

      • 推送后这是否还会清除远程仓库中的私有数据?
      • @ThomasLauria 是的,相同的清理后的 ref 在推送时被推送到远程仓库 - rtyley.github.io/bfg-repo-cleaner/#usage 的说明应该涵盖它。如果您可以控制远程仓库,您还可以在推送后对其运行“git gc --prune=now --aggressive”,以确保死对象也立即从中删除。
      • @RobertoTyley 这可能导致两个提交在历史记录中相继出现并且具有相同的树(如果其中一个提交只添加了已删除的文件)。您是否知道一种从提交历史记录中删除此类提交的简单方法,因为它们似乎是人为的?
      • @RobertoTyley 我认为这涉及另一个问题。在我描述的情况下,只涉及一个存储库。但是git filter-branch --prune-empty 似乎是我的问题的解决方案(虽然使用其他工具,请让我知道 BFG Repo-Cleaner 是否可以这样做)。
      【解决方案5】:

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

      git obliterate <filename>
      

      【讨论】:

        【解决方案6】:

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

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

        1) 确保原始 refs 已消失:

        rm -rf .git/refs/original

        2) 使所有 reflog 条目过期:

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

        3) 检查旧打包的 refs

        这可能会很棘手,具体取决于您拥有多少打包的 ref。我不知道任何可以自动执行此操作的 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 文件可能是唯一的方法。

        【讨论】:

        • 耶!!!我爱你 !问题出在打包的引用文件中,有 refs/remotes/origin/master 从我在某个服务器上备份它的时候开始......一旦我删除它,它就开始消失了......谢谢! (用完整的解决方案更新问题主体)
        【解决方案7】:

        git gc 之后 git 存储库的大小仍然很大,因为它是 does not remove all loose objects

        我在“reduce the git repository size”中详细说明了这些原因

        但在您的情况下测试的一个技巧是 clone your "cleaned" Git repo 并查看克隆是否具有适当的大小。

        ('"cleaned" repo' 是你应用filter-branch,然后是gcprune)

        【讨论】:

        • 是的,已经测试过了,现在再次测试,它减少了 2k 的存储库:) 并且文件仍然存在......
        • 奇怪的是git count-objects -v -&gt; count: 0, size: 0, in-pack: 10021, packs: 1, size-pack: 244547, prune-packable: 0, garbage: 0 但是:git clone test1 test2 -&gt; Checking out files: 100% (8509/8509), done
        【解决方案8】:

        见:How do I remove sensitive files from git’s history

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

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

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

        git gc --prune='0 days ago'
        

        【讨论】:

        • 是的,这个试过了,包里的文件还在,大小也没有太大变化……
        • 我刚做了一个git沙箱,试了一下。这里也不好。让我们看看我能弄清楚什么。
        • 答案中的那个? :) 和我发布的一样,它仍然将文件留在包中......尝试一个 git 沙箱,执行 git gc 以便它会打包文件,然后运行它......
        • 哦,松散的物体?往上看。我倾向于让它们在两周内被垃圾收集(gc 的默认值);杀死所有个松散的对象就像清空垃圾箱——我失去了找回我不小心删除的任何东西的机会。
        • :) 也试过这个...删除了一些文件,但最大的仍然存在...
        猜你喜欢
        • 2021-01-09
        • 1970-01-01
        • 1970-01-01
        • 2011-05-29
        • 2011-10-16
        • 2013-03-24
        • 2014-06-19
        相关资源
        最近更新 更多