【问题标题】:Is it possible to clean up a remote repo's files with bad commits on GitHub?是否可以在 GitHub 上清理带有错误提交的远程仓库文件?
【发布时间】:2018-04-17 03:12:51
【问题描述】:

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

考虑到 repo 的历史,我认为处理它的最简单方法是以某种方式删除旧的硬提交文件,这些文件一开始就不应该提交,这些文件可能直接或通过引用存储在某个地方。它的诀窍是,如果可以帮助,我不想弄乱历史,而且我对更高级的 git 功能了解不多,所以甚至很难知道正确的问题是什么问。

问题: 通过 GitSCM 插件通过 Jenkins 拉取/获取 repo 花费的时间太长。大约 10 分钟后超时。这个 repo 有数千个提交和几十个标签要跟踪,所以我不能随意将某个提交设置为一个好的起点并截断其余部分。

我的发现: 尝试做 GitSCM 插件似乎正在做的事情并不会导致问题或时间要求的程度。也就是说,它仍然非常慢,只是不到 10 分钟以上,所以即使插件引入了加剧的性能问题,我们也应该清理它。

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

目标:尽可能多地删除这 300 MB,而不会因丢失历史记录/标签而惹恼人们

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

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

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

鉴于此问题的背景、问题详细信息以及之前引用的问题,是否可以完成我在远程托管存储库上尝试做的事情,如果可以,我应该具体运行什么或询问我们的 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;远不及我所希望的,这就是为什么我尝试了序列中的下一个命令,当远程推送时,该命令会导致 repo 增长而不是缩小。对象数从大约 45k 增加到 60k。

【问题讨论】:

    标签: git github jenkins-plugins github-enterprise .git-folder


    【解决方案1】:

    它的诀窍是,如果可以帮助的话,我不想弄乱历史,

    但你会:git filter-branch 或(更易于使用)BFG repo cleaner 将重写该回购的提交历史(SHA1),迫使您将git push --force 最终结果返回到远程回购.
    这没什么大不了的,考虑到回购是旧的(即不再积极维护),但仍然必须考虑到。

    通过 GitSCM 插件通过 Jenkins 拉取/获取 repo 花费的时间太长。

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

    这最终导致它增长:

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

    【讨论】:

    • 现在有一些很棒的反馈和见解!如果一切顺利,我会首先尝试这个,如果一切顺利,我会接受这个作为答案,或者用实物更新:)
    • VonC,我尝试了问题中的序列,但在下面运行。这一次,.git 文件夹的大小仅减少了 1MB,而对象增长到了 59k。知道我可能做错了什么吗? git filter-branch --index-filter "git rm --cached --ignore-unmatch *.dll" --prune-empty -- --all ; git reflog expire --all --expire=now ; git gc --prune=now --aggressive ; git push --force origin master
    • @kayleeFrye_onDeck 完整序列为:stackoverflow.com/a/47194749/6309
    • VonC——产生了一个奇怪的结果。在链接到答案中的命令之前运行git-filter 时,它成功缩小了.git 文件夹的大小。在做了git push --force origin master 之后,我去重新克隆了 repo,实际上它的大小再次超过了 300MB 点。因此,这似乎可以在本地工作,但不能在远程工作;知道我错过了什么吗?也许我误解了你,需要请求我们的 GHE 管理员从 GitHub 的实际托管实例直接针对 repo 运行这些命令?
    • 顺便说一句,我没有这样做:rm -Rf .git/refs/original 因为我在任何地方都没有看到;是否有我应该执行/注意的通用等价物?我的 .git\refs 目录只包含名为 heads 的子目录; remotes ; tags
    【解决方案2】:

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

    为了通过减少 .git 文件夹中的 repo 大小来解除对远程构建的阻止,我使用了免费工具 BFG Repo Cleaner 并完全按照它的说明进行操作。它将.git 文件夹的大小从原来的 300MB 缩小到了 80MB。考虑到这个 repo 有超过 7k 次提交,我不会抱怨 .git 文件夹仍然很大。这一操作无疑大大加快了克隆 repo 的过程。

    操作方法

    完全披露:其中一些步骤是直接从 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 不在您的路径中,请将该目录临时添加到PATHSet PATH=%PATH%;C:\PathToJavaBin,或直接调用它,并确保更新此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

    就是这样:)

    【讨论】:

    • 我怀疑最后一次推送是 push --force,但除此之外我同意(并在我自己的回答中提到了 BFG)。 +1
    猜你喜欢
    • 2011-09-03
    • 2021-09-03
    • 2012-10-06
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多