是否可以通过 GitHub 上的错误提交来清理远程仓库的文件?

Is it possible to clean up a remote repo's files with bad commits on GitHub?

背景: 我的一个存储库存在一些嵌套问题,该存储库远程托管在我公司使用的 GitHub 企业版上。

考虑到回购协议的历史,我认为处理它的最简单方法是以某种方式删除旧的硬提交文件,这些文件本来不应该首先提交,这些文件可能直接或通过引用存储在某个地方.这样做的诀窍是,如果可以的话,我不想弄乱历史,而且我对更高级的 git 功能了解不多,所以很难知道正确的问题是问。

问题: 通过 GitSCM 插件通过 Jenkins pull/fetch 回购花费的时间太长。大约 10 分钟后超时。这个 repo 有数千个提交和几十个标签需要跟踪,所以我不能随意将某个提交设置为一个好的起点,然后 运行 处理其余的。

我的发现: 尝试执行 GitSCM 插件似乎正在执行的操作几乎不会导致问题的严重程度或时间要求。也就是说,它仍然非常慢,只是不会慢 10 分钟以上,所以即使插件引入了更严重的性能问题,我们也应该清理它。

可能的优化: 我发现有几个提交主要是添加 DLL。这些 DLL 已通过新提交删除。然而,与本地文件系统实际使用的大小相比,repo 的大小仍然是数百兆字节。现在,master 分支在 .git 文件夹之外大约 4MB,大约 300 MB。

目标: 尽可能多地处理掉这 300 MB,而不会因丢失 history/tags

而惹恼别人

我已经尝试了很多可能相关问题的解决方案,但我无法在远程托管存储库精简到更接近文件系统使用的实际大小的地方得到它。其中一些问题是,

Reduce git repository size
How to remove unused objects from a git repository?
Why won’t git further reduce the repository size?

在尝试了这些问题的解决方案后,我最终只增加了存储库的大小而不是减少了它,公平地说,我在其中一个问题的答案中被警告过。

考虑到这个问题的背景、问题的细节以及之前提到的问题,是否可以完成我在远程托管存储库上尝试做的事情,如果可以,我具体应该做什么 运行 或询问我们的 GHE 管理员 运行 如果我个人无法进行更新?

这最终导致它增长:

git reflog expire --all --expire=now
git gc --prune=now --aggressive
git filter-branch --index-filter "git rm --cached --ignore-unmatch *.dll" --prune-empty -- --all
git push origin master

然而,在 运行执行前两个命令后,我只看到 .git 文件夹的大小减少了 40 MB;与我所希望的相去甚远,这就是为什么我尝试了序列中的下一个命令,当远程推送时导致回购增长而不是缩小。对象数从大约 45k 增加到 60k。

The trick of that it is, I don't want to mess with the history if it can be helped,

但你会:git 过滤器分支或(更易于使用)BFG repo cleaner 将重写该回购提交的历史记录 (SHA1),迫使你 git push --force 最终结果返回远程仓库。
这没什么大不了的,考虑到回购协议是旧的(即不再积极维护),但仍然必须考虑在内。

The repo is taking too long to pull/fetch down via Jenkins, via the GitSCM plugin.

这里根本不应该涉及 Jenkins:您可以在本地克隆 repo,清理它,然后将其推回。
另外,可以提高 Jenkins 中的超时。

This ended up causing it to grow:

这些 reflog/gc 命令应该在过滤器分支或 BFG 之后 使用,而不是之前。

我不会接受我自己的回答。 VonC 完成了一项令人钦佩的任务,试图在评论中修改答案以满足我非常具体的要求,这可能不会阻止其他人遇到类似问题——此外,VonC 确实提到了使用 BFG,这最终让我解除了封锁。让它只与 git 一起工作会很好,但由于 BFG 是完全免费的(而且比 git filter-branch 快得多)我不能忽视它作为处理 git 的替代方法问题。

为了通过减少 .git 文件夹中的存储库大小来取消阻止我们的远程构建,我使用了免费工具 BFG Repo Cleaner 并严格按照其说明进行操作。它运行k .git 文件夹的大小从原来的 300MB 减小到 80MB。考虑到这个 repo 有超过 7k 的提交,我不会抱怨 .git 文件夹仍然很大。此操作明显加快了能够克隆存储库的过程。

操作方法

完全披露:其中一些步骤是直接从 BFG Repo Cleaner 的文档中复制的,链接到步骤 #2。它还假定您正在使用 Windows,因此请根据需要更新 shell 语法。

  1. 如果您还没有 Java,请安装
  2. 从他们的网站 here 下载免费工具 BFG Repo Cleaner,这也是他们的文档页面
  3. 如果您不想执行与我完全相同的操作,即我删除 .DLL 的所有文件类型,请查看 BFG 的简短文档以了解还有哪些可用的
  4. 打开命令控制台并使用 --mirror 为您的存储库执行浅克隆,例如:
    git clone --mirror https://github.com/some-big-repo.git
  5. 如果 java.exe 不在您的路径中,请使用 Set PATH=%PATH%;C:\PathToJavaBin 将该目录临时添加到 PATH,或者直接调用它,并确保更新此命令JAR 文件的名称,因此下面的命令与您的文件系统中的内容相匹配,例如:
    C:\PathToJavaBin\java.exe -jar C:\PathToBFGJar\bfg.jar --delete-files *.dll some-big-repo.git
  6. 运行 cd some-big-repo.git
  7. 运行 git reflog expire --expire=now --all
  8. 运行 git gc --prune=now --aggressive
  9. 运行 git push

就是这样 :)