如何从Git';什么是历史?

如何从Git';什么是历史?,git,git-rewrite-history,Git,Git Rewrite History,如何从Git的历史记录中永久删除提交 团队中的一名开发人员意外提交了一个200 MB的文件,并将其推送到我们的Git服务器。几天后它被删除了,但历史记录仍然存在。我们的代码文件只有大约75MB,我们有4个分支。由于200 MB的文件提交,历史记录被保留,项目文件夹(特别是隐藏的.git文件夹)的大小已膨胀到接近700 MB。如何从git中永久删除这两个签入(提交大文件,删除大文件),就好像它从未发生过一样?如果有必要的话,我正在使用“龟甲”(TortoiseGit)。你可以使用git。请注意,这

如何从Git的历史记录中永久删除提交


团队中的一名开发人员意外提交了一个200 MB的文件,并将其推送到我们的Git服务器。几天后它被删除了,但历史记录仍然存在。我们的代码文件只有大约75MB,我们有4个分支。由于200 MB的文件提交,历史记录被保留,项目文件夹(特别是隐藏的.git文件夹)的大小已膨胀到接近700 MB。如何从git中永久删除这两个签入(提交大文件,删除大文件),就好像它从未发生过一样?如果有必要的话,我正在使用“龟甲”(TortoiseGit)。

你可以使用git。请注意,这涉及到历史重写,所有克隆都需要重新创建。你可以在专业的Git书籍中找到一个很好的方法。

正如forvaidya所建议的,
Git过滤器分支
是一个不错的选择。具体而言,在您的情况下,您可以执行以下命令从回购历史记录中删除该文件:

git filter-branch --tree-filter 'rm -f filename' HEAD
用实际文件名替换
filename
。同样,正如forvaidya所说,这重写了回购协议的整个历史,所以任何在你做出这一改变后退出的人都会犯错误

Edit:出于性能原因,实际上最好使用Git的
rm
命令:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD
从签出中删除该文件 Github提供了如何从存储库中永久删除文件的方法,简而言之:

$ git filter-branch --force --index-filter \
  'git rm --cached --ignore-unmatch 200MB-filename' \
  --prune-empty --tag-name-filter cat -- --all
$ git push --all -f
这将从所有分支中删除该文件。然后,要在本地恢复空间,请执行以下操作:

$ rm -rf .git/refs/original/
$ git reflog expire --expire=now --all
$ git gc --prune=now
正在恢复git服务器上的空间 强制推送不会删除远程服务器上的任何提交/对象。如果不想等待git自行清理,可以在服务器上显式运行它:

$ ssh git server
$ cd /my/project/repo.git
$ git gc --prune=now
比较回购前后的规模——确保它是您预期的规模。如果在将来的任何时候它恢复到较大的大小-有人将已删除的提交推回到存储库中(需要再次执行所有步骤)

队友 如果有其他开发人员使用此存储库,他们将需要清理他们的签出。否则,当他们从存储库中提取并推送更改时,他们将添加回已删除的文件,因为该文件仍在本地历史记录中。有两种方法可以避免这种情况:

  • 再次克隆
  • 获取并重置
  • 第一个很简单,第二个意思是两件事之一:

    用户没有本地提交 这将使任何本地签出与远程签出完全匹配

    用户没有本地提交 用户需要确保没有任何引用删除文件的本地提交,否则会将其添加回存储库

    用户清理 然后(可选,因为git不会将未引用的提交推送到服务器)恢复空间,每个人都有一个一致的更精简的存储库状态:

    $ rm -rf .git/refs/original/
    $ git reflog expire --expire=now --all
    $ git gc --prune=now
    
    我建议您尝试一下——它不会删除这两个提交,但会重写历史,以从您的历史中删除大量文件

    仔细遵循BFG的要求-核心部分如下:

    $ java -jar bfg.jar  --strip-blobs-bigger-than 100M  my-repo.git
    
    它也大大快于大型存储库上的git filter branch——你可能会发现这个速度比较视频很有趣——BFG运行在Raspberry Pi上,git filter branch运行在四核Mac OS X盒上。。。哪个更快

    请注意,在清理之后,您应该运行以使Git识别出它不再需要存储那些大对象,并释放存储库副本中的磁盘空间
    git gc
    通常在大多数托管版本的git上定期发生,因此当您将清理的历史记录推送到主git服务器时,该服务器最终也会释放磁盘空间。也许令人惊讶的是,您不必等到
    git gc
    运行之后,用户就可以克隆干净的repo的新副本,从而获得干净的历史记录


    全面披露:我是BFG回购清理程序的作者。

    如果是最近提交的,最简单的方法是:

    # check how many MB your .git dir is before you start
    du -m -d0 .git
    
    # rebase to remove the commits with large files
    git rebase -i HEAD~2 # or however many commits you need to go back
    
    # force push to remote origin
    git push -f origin HEAD
    
    现在重新整理回购协议,检查大文件是否消失。在新目录中执行此操作

    git clone <url> <new dir>
    
    # check MB of .git dir (should be smaller by the size of the large file)
    du -m -d0 .git
    
    git克隆
    #检查.git dir的MB(应小于大文件的大小)
    du-m-d0.git
    
    如果成功了,那么其他开发人员回到正轨的最干净的方法就是重新选择一个新的目录并手动应用他们正在进行的工作。如果.git大小没有减少,请检查是否有标记或任何引用违规提交的内容。您还必须删除引用源提交的任何标记


    对于更复杂的情况,您可以通过AD7six尝试答案,但这只是一种简单而干净的方法。

    虽然BFG本身不会恢复与BFG删除的历史记录项相关的空间,但它表明在BFG之后运行
    git gc
    将:摘录:“BFG将更新您的提交以及所有分支和标记,使它们保持干净,但不会实际删除不需要的内容。检查repo以确保您的历史记录已更新,然后使用标准的
    git gc
    命令去除不需要的脏数据,git现在将其识别为超出要求的数据:“(有关实际命令行,请参阅BFG doc)。”哇,在检查您的个人资料时,我刚刚发现您是BFG的作者。:-)我是否正确地解释了BFG文档,
    git gc
    确实恢复了先前分配给BFG从repo历史中删除的文件的空间?@davidr您对BFG文档所说的是正确的-是的,您你可以运行
    git gc
    !我更新了我的问题,给出了一些标准的免责声明…令人惊讶的是,重写git历史的过程有多少种方式可以偏离正轨,只要人们遵循,他们应该是可以的…请看更长一点的讨论!感谢你的澄清和创建这样一个有用的工具。我投票支持c将此问题作为您所在位置的副本丢失。可能是的副本
    # check how many MB your .git dir is before you start
    du -m -d0 .git
    
    # rebase to remove the commits with large files
    git rebase -i HEAD~2 # or however many commits you need to go back
    
    # force push to remote origin
    git push -f origin HEAD
    
    git clone <url> <new dir>
    
    # check MB of .git dir (should be smaller by the size of the large file)
    du -m -d0 .git