从Git历史记录中删除二进制文件后,为什么我的存储库仍然很大?

时间:2012-06-29 03:46:07

标签: git version-control github

所以,让我在这个问题前面说,我知道之前有关Stackoverflow主题的问题。事实上,我已经尝试了所有可以找到的解决方案,但我的仓库中有一个二进制文件,只是拒绝被删除,并继续大大膨胀我的回购协议大小。

我试过的方法,

这两个都是由Darhuuk对Remove files from git repo completely

的回答推荐的

然而,在尝试了这两种解决方案后,script to find large files in git仍然找到了违规的二进制文件。但是,来自this answer的脚本不再找到二进制文件的提交。这两个脚本都是this answer建议的。

在尝试移除后,回购仍然是44mb,这对于相对较小的源来说太大了。大文件脚本正在做哪些工作正常工作。我已经尝试过推到github(我做了一个叉子以防万一),然后做一个新的克隆,看看回购大小是否减少,但它仍然是相同的大小。

有人可以解释我做错了什么或建议替代方法吗?

我应该注意到,我不仅仅对从我的本地仓库修剪文件感兴趣,我还希望能够在Github上修复远程仓库。

4 个答案:

答案 0 :(得分:24)

2017编辑:如果您正在阅读本文,您应该查看BFG Repo-Cleaner


令人尴尬的是,我的本地存储库大小没有缩小的原因是因为我在filter-branch中使用了错误的文件路径。因此,当我感谢J-16 SDiZ和CodeGnome的答案时,我的问题出在椅子和键盘之间。

为了使这个问题不再是我愚蠢的一个纪念碑,并且实际上对人们有用,我花了很多时间写下修剪回购后必须经历的步骤才能获得repo备份在Github上。希望这可以帮助某人走出困境。


删除违规文件

要删除有问题的文件,请根据Github remove sensitive data howto

运行下面的shell脚本
#!/usr/bin/env bash
git filter-branch --index-filter 'git rm -r -q --cached --ignore-unmatch '$1'' --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

我浏览了本地存储库中的每个分支并执行了此操作,但老实说我不确定是否需要这样做,(您不需要在每个分支上执行此操作)然而,确实需要每个分支机构进行下一步,所以请记住这一点。完成后,您应该会看到当地仓库的尺寸减小。您还应该能够在CodeGnome的答案中运行blob脚本,并查看有问题的blob删除。如果没有仔细检查文件名和路径,请确保它们是正确的。

git filter-branch实际上在这里做的是运行repo中每个提交的引号中列出的命令。

脚本的其余部分只清除旧数据的任何缓存版本。

推动修剪后的仓库

既然本地仓库处于你需要它的状态,那就是把它重新安装到Github上。不幸的是,据我所知,没有办法从Github仓库中完全删除二进制数据,这里引用Github sensitive data howto

  

请注意,强制推送不会删除远程仓库上的提交,它只会引入新的并将分支指针移动到指向它们。如果您担心用户直接通过SHA1访问错误提交,则必须删除存储库并重新创建它。

你很难重新创建Github仓库,但重新创建仓库的好消息实际上非常简单。痛苦的是你还必须在问题和维基中重新创建数据,我将在下面介绍。

我建议在github中创建一个新的repo,然后在准备就绪时用旧的repo将其切换出来。这可以通过将旧的名称重命名为" repo name old"然后将新创建的仓库的名称更改为" repo name"。确保在创建新的repo时取消选中使用README进行初始化,否则你将不会处理干净的平板。

如果你完成了最后一步,你应该清理你的仓库并准备好了。现在需要更改遥控器以匹配新的Github repo位置。我通过直接编辑.git / config文件来做到这一点,但我确信有人会告诉我这不是正确的方法。

在进行推送之前,请确保您想要在本地仓库中推送所有分支和标签。准备就绪后,使用以下

推送所有分支
git push --all
git push --tags

现在你应该有一个远程仓库来匹配你修剪过的本地仓库。仔细检查所有数据是否以防万一。

现在,如果你不必担心问题或wiki,你就完成了。如果您继续阅读。

移动wiki

Github wiki只是与你的主要回购相关的另一个回购。所以开始克隆你的旧维基回购地点。然后下一部分有点棘手,据我所知,你需要点击新repo的wiki选项卡来创建wiki,但是它会为新创建的wiki播种一个初始文件。所以我做了什么,我不确定是否有更好的方法,是将遥控器更改为新创建的维基回购并使用

推送到新位置
git push --all --force

这里需要力量,因为否则git会抱怨当前分支的尖端不匹配。我认为这可能会使git repo中的初始页面处于分离状态,但是这对repo大小的影响应该可以忽略不计。

转移问题

this answer给出了有关此问题的建议。但是看看答案中链接的the script看起来相当不完整,有一个用于评论导入的TODO,我无法判断它是否会带来问题状态。

所以考虑到我有一个相当小的公开问题队列,我不介意失去封闭的问题,我选择手动把事情搞砸。请注意,在评论中向其他人正确归属是不可能的。所以我认为对于一个更大的更成熟的项目,你需要编写一个更强大的脚本来把所有东西都放在一边,但我的特殊情况并不需要。

答案 1 :(得分:19)

假设您已经使用git-filter-branch(1)和朋友从历史记录中删除了blob,Git经常在reflogs,packfiles和松散的存储库对象中保留一些东西。删除这些未引用对象的咒语是:

git prune --expire=now
git reflog expire --expire-unreachable=now --rewrite --all
git repack -a -d
git prune-packed

如果你已经完成了这个并且仍然拥有比你想象的更大的存储库,那么你仍然可以在存储库中引用你的blob 某处。你必须回到第一步并删除它们。这可能会有所帮助:

# List all blobs by size in bytes.
git rev-list --all --objects   |
    awk '{print $1}'           |
    git cat-file --batch-check |
    fgrep blob                 |
    sort -k3nr

答案 2 :(得分:6)

script to find large files in git中的脚本检查.pack文件 - 即原始对象存储库。第二个脚本显示不再引用大对象。如果您真的想要清理它,可以执行gcrepack

git gc --aggressive --prune=now
git repack -A -d

如果仍然没有帮助,您可能在远程分支中有对象引用,您可以尝试

  1. 找出具有此对象的提交,请参阅Which commit has this blob?并执行git branch -a --contains <commit-ish>
  2. 使用git branch -r -D branchname
  3. 删除远程分支

    更新 - 什么是“远程分支”?

    • 当您执行git fetch / git pull时,远程分支是git获取内容的内容。 (git pullgit fetch refspec + git merge remote-branch相同。

    • 如果从远程存储库进行克隆,删除远程分支应该没有任何不良影响 - 您始终可以使用类似git fetch origin refs/heads/master:refs/remotes/origin/master的内容再次从远程获取/拉取(这会拉{{1}从远程分支到远程分支master)。

    • 如果这个分支是由你创建的,删除也应该没问题 - 因为你应该有一个“正常”(跟踪)分支。 你应该加倍确认。

答案 3 :(得分:2)

  

有人可以解释我做错了什么或建议替代方法吗?

您是否尝试过应用DMAIC? D efine, M easure, A nalyze,改进, C ontrol。

D - 从git历史记录中删除文件后,我的回购仍然很大 M - 使用git init确定新鲜仓库的大小以建立基线 A - 识别,验证和选择根本原因。试验git-repo-analysis 我 - 识别,测试和实施解决方案。也许BFG Repo-Cleaner会有所帮助。也许它不会。
C - 保持收益。看看Git LFS或其他适当的控制方法。

  

我也希望能够在Github上修复远程仓库。

这取决于您选择如何解决问题。例如,当使用BFG从历史中修剪文件时,它将重写历史记录并更新提交SHA,因此根据您的特定需求和期望的结果,将会有一些给予和接受。