26

因此,让我先说我知道与 Stackoverflow 上的主题有关的先前问题。事实上,我已经尝试了所有我能找到的解决方案,但我的仓库中有一个二进制文件拒绝被删除,并继续大大增加了我的仓库大小。

我试过的方法,

这两个都是 Darhuuk 对Remove files from git repo的回答推荐的

但是,在尝试了这两种解决方案之后,在 git 中查找大文件的脚本仍然会找到有问题的二进制文件。但是,此答案中的脚本不再找到二进制文件的提交。这两个脚本都是由这个答案建议的。

尝试删除后,repo 仍然是 44mb,这对于相对较小的源大小来说太大了。哪些建议大文件脚本正确地完成了它的工作。我试过推到 github(我做了一个 fork 以防万一),然后做一个新的克隆,看看 repo 大小是否减小,但它仍然是相同的大小。

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

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

4

4 回答 4

27

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

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

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

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

推送修剪后的回购

现在本地存储库处于您需要的状态,诀窍就是将其备份到 Github 上。不幸的是,据我所知,没有办法从 Github 存储库中完全删除二进制数据,这是Github 敏感数据操作指南的引用

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

您需要重新创建 Github 存储库,这很糟糕,但好消息是重新创建存储库实际上非常容易。痛苦是您还必须在问题和 wiki 中重新创建数据,我将在下面介绍。

我建议在 github 中创建一个新的 repo,然后在你准备好时用旧的 repo 将其切换出来。这可以通过将旧的重命名为“repo name old”,然后将新创建的 repo 的名称更改为“repo name”来完成。确保在创建新存储库时取消选中使用 README 进行初始化,否则您将无法处理干净的状态。

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

在进行推送之前,请确保您在本地存储库中拥有要推送的所有分支和标签。准备好后,使用以下命令推送所有分支

git push --all
git push --tags

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

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

移动 wiki

Github wiki 只是与您的主存储库相关联的另一个存储库。因此,要开始在某处克隆您的旧 wiki 存储库。然后下一部分有点棘手,据我所知,您需要单击新存储库的 wiki 选项卡才能创建 wiki,但它会使用初始文件为新创建的 wiki 播种。所以我所做的,我不确定是否有更好的方法,将遥控器更改为新创建的 wiki repo 并使用推送到新位置

git push --all --force

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

转移问题

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

因此,鉴于我有一个相当小的未解决问题队列,并且我不介意丢失已解决的问题,我选择手动解决问题。请注意,在评论中正确归因于其他人是不可能做到这一点的。因此,我认为对于一个更成熟的大型项目,您需要编写一个更强大的脚本来完成所有工作,但对于我的特定情况,这不是必需的。

于 2012-06-30T20:34:59.600 回答
22

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

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
于 2012-06-29T06:31:25.010 回答
6

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

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

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

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

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

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

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

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

于 2012-06-29T03:51:36.327 回答
1

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

您是否尝试过申请 DMAIC?定义测量分析、改进控制

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

我还希望能够修复 Github 上的远程仓库。

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

于 2017-05-26T05:08:38.097 回答