8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何从 Git 存储库的提交历史记录中移除/删除大文件?

Stoycho Andreev 1月前

142 0

我无意中将 DVD-rip 放入了一个网站项目中,粗心地 git commit -a -m ...,然后,存储库就膨胀了 2.2 GB。下次我进行一些编辑时,删除了视频文件,然后

我无意中将 DVD-rip 放入了一个网站项目中, git commit -a -m ... 结果存储库膨胀了 2.2 GB。下次我进行一些编辑,删除视频文件并提交所有内容,但压缩文件仍然存在于存储库的历史记录中。

我知道我可以从这些提交开始分支,并将一个分支重新定位到另一个分支。但是我应该怎么做才能合并这两个提交,以便大文件不会显示在历史记录中并在垃圾收集过程中被清除?

帖子版权声明 1、本帖标题:如何从 Git 存储库的提交历史记录中移除/删除大文件?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Stoycho Andreev在本站《eclipse》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 保存当前代码的备份,以防在此过程中出现任何问题。

    git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch path/to/large_file' --prune-empty --tag-name-filter cat -- --all
    

    将 path/to/large_file 替换为您要删除的大文件的实际路径。此命令将重写 Git 历史记录并从所有提交中删除大文件。

    运行 git filter-branch 命令后,您可能会看到一条消息,显示“Ref 'refs/heads/master' is changing”或类似内容。这表明分支尚未更新。要更新分支并应用更改,请使用:

    git push origin --force --all
    
  • 我有同样的问题。因此, git rebase -i HEAD~15 我将包含大文件的提交转换为 edit 模式,然后 git rm {relative/path/largeFile} 从提交中删除大文件并执行 git rebase --continue .

    我还添加 {relative/path/largeFile} filter=lfs diff=lfs merge=lfs -text .gitattributes 提交了。

    请注意, git filter-repo 尽管消息成功,但对我来说不起作用。注意我 git clone https://github.com/newren/git-filter-repo.git 在另一个目录中克隆了。然后从该目录运行 python git-filter-repo --path "{large\File\Path}" --invert-paths .

  • 除了 git filter-branch (缓慢但纯 git 解决方案)和 BFG (更简单且性能更高)之外,还有另一个性能良好的过滤工具:

    https://github.com/xoofx/git-rocket-filter

    根据其描述:

    git-rocket-filter 的用途与命令类似, git-filter-branch 但提供以下独特功能:

    • 快速重写提交和树(按 x10 到 x100 的顺序)。
    • 内置支持使用 --keep 选项的白名单(保留文件或目录)和使用 --remove 选项的黑名单。
    • 使用类似 .gitignore 的模式进行树状过滤
    • 用于提交过滤和树过滤的快速简便的 C# 脚本
    • 支持根据文件/目录模式进行树形过滤的脚本
    • 自动修剪空的/未改变的提交,包括合并提交
  • G.M 1月前 0 只看Ta
    引用 5

    您可以使用以下命令执行此操作 branch filter

    git filter-branch --tree-filter 'rm -rf path/to/your/file' HEAD

  • 当你遇到这个问题时, git rm 这是不够的,因为 git 会记得该文件在我们的历史记录中存在过一次,因此会保留对它的引用。

    更糟糕的是,重新定基也不容易,因为对 blob 的任何引用都会阻止 git 垃圾收集器清理空间。这包括远程引用和 reflog 引用。

    我编写了 git forget-blob 一个小脚本,尝试删除所有这些引用,然后使用 git filter-branch 重写分支中的每个提交。

    一旦你的 blob 完全不再被引用, git gc 就会删除它

    使用方法非常简单 git forget-blob file-to-forget 。你可以在这里获取更多信息

    https://ownyourbits.com/2017/01/18/completely-remove-a-file-from-a-git-repository-with-git-forget-blob/

    我根据 Stack Overflow 上的回答和一些博客文章整理了这篇文章。感谢他们!

  • 评论 非常有用,我决定将其作为答案发布,以便更多人看到它。

    他们说使用 git-filter-repo 并运行命令: git filter-repo --strip-blobs-bigger-than 10M

    如果你在 Windows 上安装时遇到困难 git-filter-repo (就像我一样),请参阅.

    这是做什么的?它是如何工作的?我不知道。如果你知道,请发表评论。

    但是,之后,我的提交历史记录中仍然保留着所有大文件,而这些大文件不再存在于提交历史记录中。它起作用了。

    与往常一样, 在运行此操作之前备份你的仓库 .

  • Sv. 1月前 0 只看Ta
    引用 8

    git lfs migration import --above=\'100 MB\' --一切都对我有用,但需要先用 \'git lfs install\' 初始化 Git LFS

  • 在我看来, git lfs migrate ... 是更好的选择。它简单、快速、易于使用,并且不需要额外安装。对于重写 git 历史记录以将大文件移动到 LFS 的任务,您需要和 info import 命令。 docs , 教程

    对于我今天的工作,最终的解决方案是:

    git clone [remote_path_to_repo] repo_cleanup
    cd repo_cleanup
    # Ensure my local checkout is complete..
    git lfs fetch all
    
    # Dry run of looking for all file types above 10MB
    git lfs migrate info --above=10MB --everything
    
    # Migrate & rewrite local history
    git lfs migrate import --above=10MB --everything
    
    # Force-push to overwrite remote history
    # This will break compatibility with all existing checkouts!
    # Ensure you first coordinate with all other developers to make fresh checkouts.
    git push -f --mirror
    

    无论如何,我发现它 git lfs migrate 比 BFG Repo-Cleaner 更方便、更实用。我没有尝试, filter-branch 因为它看起来太复杂了。

  • git filter-branch 是一个强大的命令,你可以使用它从提交历史记录中删除一个大文件。该文件将保留一段时间,Git 将在下一次垃圾收集时将其删除。以下是从 提交历史记录中删除文件 。为了安全起见,下面的过程首先在新的分支上运行命令。如果结果是你需要的,则将其重置回你真正想要更改的分支。

    # Do it in a new testing branch
    $ git checkout -b test
    
    # Remove file-name from every commit on the new branch
    # --index-filter, rewrite index without checking out
    # --cached, remove it from index but not include working tree
    # --ignore-unmatch, ignore if files to be removed are absent in a commit
    # HEAD, execute the specified command for each commit reached from HEAD by parent link
    $ git filter-branch --index-filter 'git rm --cached --ignore-unmatch file-name' HEAD
    
    # The output is OK, reset it to the prior branch master
    $ git checkout master
    $ git reset --soft test
    
    # Remove test branch
    $ git branch -d test
    
    # Push it with force
    $ git push --force origin master
    
  • 引用 11

    Git Extension 很好用,很简单。但是它内部使用了 git filter-branch,因此删除速度很慢。

  • 没有用过,但是根据本页上的另一个答案,我用的是 BFG Repo-Cleaner。

  • vzsg 1月前 0 只看Ta
    引用 13

    对于大型存储库来说,这种方法实在是太慢了。列出大型文件需要一个多小时。然后当我去删除文件时,一个小时后,我想要删除的第一个文件才处理了三分之一。

  • 使用 Git Extensions ,它是一个 UI 工具。它有一个名为“查找大文件”的插件,可以查找存储库中的大文件并允许永久删除它们。

    在使用此工具之前不要使用“git filter-branch”,因为它无法找到被“filter-branch”删除的文件(尽管“filter-branch”不会从存储库包文件中完全删除文件)。

  • 我基本上按照这个答案做了: https://.com/a/11032521/1286423

    (关于历史,我将其复制粘贴到这里)

    $ git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch YOURFILENAME" HEAD
    $ rm -rf .git/refs/original/ 
    $ git reflog expire --all 
    $ git gc --aggressive --prune
    $ git push origin master --force
    

    它不起作用,因为我喜欢重命名和移动很多东西。所以一些大文件位于已重命名的文件夹中,我认为 gc 无法删除对这些文件的引用,因为 tree 指向这些文件的对象中有引用。我真正杀死它的最终解决方案是:

    # First, apply what's in the answer linked in the front
    # and before doing the gc --prune --aggressive, do:
    
    # Go back at the origin of the repository
    git checkout -b newinit <sha1 of first commit>
    # Create a parallel initial commit
    git commit --amend
    # go back on the master branch that has big file
    # still referenced in history, even though 
    # we thought we removed them.
    git checkout master
    # rebase on the newinit created earlier. By reapply patches,
    # it will really forget about the references to hidden big files.
    git rebase newinit
    
    # Do the previous part (checkout + rebase) for each branch
    # still connected to the original initial commit, 
    # so we remove all the references.
    
    # Remove the .git/logs folder, also containing references
    # to commits that could make git gc not remove them.
    rm -rf .git/logs/
    
    # Then you can do a garbage collection,
    # and the hidden files really will get gc'ed
    git gc --prune --aggressive
    

    我的 repo( .git )从 32MB 变为 388KB,甚至连 filter-branch 都无法清理。

  • Ruth 1月前 0 只看Ta
    引用 16

    @mkljun,请至少删除“git push origin master --force”!首先,这与原始问题无关 - 作者没有询问如何编辑提交并将更改推送到某个存储库。其次 - 这很危险,您确实可以删除大量文件并将更改推送到远程存储库,而无需先检查删除了什么,这不是一个好主意。

  • 引用 17

    我使用了这个命令:git filter-branch --force --index-filter 'git rm --cached -r --ignore-unmatch oops.iso' --prune-empty --tag-name-filter cat -- --all,而不是代码中的第一个

  • 除非您想给自己带来巨大的痛苦,否则请不要运行这些命令。它删除了我很多原始源代码文件。我以为它会从 GIT 中的提交历史记录中清除一些大文件(根据原始问题),但是,我认为此命令旨在永久清除原始源代码树中的文件(有很大区别!)。我的系统:Windows,VS2012,Git 源代码控制提供程序。

  • 请注意,这些命令可能非常具有破坏性。如果更多人正在处理存储库,他们都必须拉出新树。如果您的目标不是 减小 大小,则中间三个命令不是必需的。因为过滤器分支会创建已删除文件的备份,并且它可以保留很长时间。

    git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch YOURFILENAME" HEAD
    rm -rf .git/refs/original/
    git reflog expire --all
    git gc --aggressive --prune
    git push origin master --force
    
  • 如果您知道您的提交是最近的,则无需遍历整个树,请执行以下操作: git filter-branch --tree-filter 'rm LARGE_FILE.zip' HEAD~10..HEAD

返回
作者最近主题: