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

Jam*_*hon 24 git version-control github

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

方法我试过,

这两个都是由Darhuuk 完全从git repo中删除文件的答案推荐的

但是,在尝试这两种解决方案之后,在git中查找大文件脚本仍然会找到违规的二进制文件.但是,此答案中的脚本不再找到二进制文件的提交.这个答案都提出了两个脚本.

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

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

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

Jam*_*hon 24

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


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

为了使这个问题不再成为我愚蠢的纪念碑并且对人们有用,我花了很多时间来编写修剪回购后必须经历的步骤,以便在Github上重新获得回购.希望这可以帮助某人走出困境.


删除违规文件

要删除有问题的文件,请运行下面的shell脚本,根据Github删除敏感数据howto

#!/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
Run Code Online (Sandbox Code Playgroud)

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

什么git的过滤分支实际上这里做的是运行在每个引号中列出的命令提交的回购.

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

推动修剪后的回购

现在本地仓库处于状态,你需要它才能让它在Github上重新启动.不幸的是,据我所知,没有办法从Github repo中完全删除二进制数据,这里是来自Github敏感数据的引用howto

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

很糟糕,你需要重新创建Github回购,但重新创建回购的好消息实际上非常简单.痛苦的是你还必须在问题和维基中重新创建数据,我将在下面介绍.

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

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

在进行推送之前,请确保您拥有要在本地仓库中推送的所有分支和标签.一旦准备就绪,请使用以下内容推送所有分支

git push --all
git push --tags
Run Code Online (Sandbox Code Playgroud)

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

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

移动wiki

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

git push --all --force
Run Code Online (Sandbox Code Playgroud)

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

移动问题

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

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


Tod*_*obs 21

假设您已经使用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
Run Code Online (Sandbox Code Playgroud)

如果你已经完成了这个并且你仍然有一个比你想象的更大的存储库,那么你仍然可以在存储库中的某个地方引用你的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
Run Code Online (Sandbox Code Playgroud)


J-1*_*DiZ 6

脚本中用于在git中查找大文件的脚本检查.pack文件 - 即原始对象存储库.第二个脚本显示不再引用大对象.如果你真的想要清理它,你可以做一个gcrepack:

git gc --aggressive --prune=now
git repack -A -d
Run Code Online (Sandbox Code Playgroud)

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

  1. 找出哪个提交有这个对象,看看哪个提交有这个blob?并做git branch -a --contains <commit-ish>
  2. 使用删除远程分支 git branch -r -D branchname

更新 - 什么是"远程分支"?

  • 远程分支是git在执行git fetch/ 时获取的东西git pull.(git pullgit fetch refspec+ 相同git merge remote-branch.

  • 如果从远程存储库克隆,删除远程分支应该没有任何不良影响 - 您可以使用类似的东西git fetch origin refs/heads/master:refs/remotes/origin/master(这将master分支从远程分支拉到远程分支remotes/origin/master)再次从远程获取/拉取.

  • 如果这个分支是由你创建的,那么删除也应该没问题 - 因为你应该有一个"正常"(跟踪)分支.你应该双重确认这一点.


归档时间:

查看次数:

10206 次

最近记录:

8 年,6 月 前