BFG 复制了我之前的提交以及 "clean" 次提交

BFG duplicated my previous commits along with "clean" commits

我试图删除一些 files/folders 不小心通过 BFG 上传到我的远程 git 存储库,在遵循指南后,我似乎有重复的提交 -- 一组分支被清除数据的一组,一组仍然有数据。这是证明这一点的网络图:https://github.com/barricklab/pLannotate/network

我先:

git clone --mirror https://github.com/barricklab/pLannotate.git

然后我使用了几个类似的命令:

bfg --delete-files *.gbk

并最终使用:

git reflog expire --expire=now --all && git gc --prune=now --aggressive

git push

我意识到有一个本地提交在我克隆之前没有被推送,所以这可能与它有关吗?我不确定。在这一点上,我害怕对存储库造成更多损害,我不确定如何删除仍然包含我试图删除的文件的备用分支集。

在初始分支突出显示“好”(文件已删除)和“坏”(文件仍然存在)分支后,第一次提交到存储库:

https://github.com/barricklab/pLannotate/commit/e146338a62cda43f4d09df90ce90472807f0b60b https://github.com/barricklab/pLannotate/commit/01b5ee7bbb697d3aba30d4d2944ae716dfc53ab9

谁能帮我摆脱困境并删除这组重复的分支?

... after following [the] guide, I seem to have duplicated commits

这就是 BFG 的运作方式。

这就是使用 Git 完成此类工作的 任何东西 的工作方式,因为 任何提交都不能更改 . “修复”错误的提交实际上是不可能的。任何人或任何事唯一能做的就是进行新的“重复”(但略有不同)提交,它会获得一个新的不同的哈希 ID。

因为提交形式 chains,并且 Git 从 last 提交到第一个提交,任何你想要的更改made 需要更新每个后续提交,即使后续提交的文件快照与原始文件 100% 相同:

A  <-B  <-C  <-D  <-E  <-F  <-G  <-H   <--main
                    ^
                    |
   let's say this commit is bad: has a big file

要“修复”这个大文件问题,即使在提交 F 中删除了大文件,我们也必须 copy 提交 E 到一个新的和改进的提交 E':

A--B--C--D--E--F--G--H
          \
           E'

完成后,我们现在必须将提交 F 复制到新的和改进的 F',唯一的变化是 F' 指向 E',而不是原来的(坏)E:

A--B--C--D--E--F--G--H
          \
           E'-F'

完成后,出于同样的原因,我们被迫复制 G,并再次复制 H。最后的结果是:

           E--F--G--H   [abandoned]
          /
A--B--C--D--E'-F'-G'-H'   <--main

BFG 和其他 Git 修复者将 if/when 适当地完全丢弃旧的提交(Git 喜欢尽可能长时间地保留它们)。但是如果你再次将这个新的仓库引入old仓库,old仓库会说:Oh, I see you'缺少这些提交,E-F-G-H 并立即将它们还给您并让您合并它们:

           E---F--G---H
          /            \
A--B--C--D--E'-F'-G'-H'-M   <--main

现在您有了旧提交 新提交。解决这个问题的方法是确保您永远不会将更改后的 new 存储库接触到任何 old 存储库,以便Git 使用 old 存储库无法返回您在创建新提交时清除的旧提交。

换句话说,不要使用过滤前的版本重新加入过滤后的存储库,否则您会带回刚刚努力摆脱的所有内容。

如果您重新加入旧提交,则修复混乱

要删除上面 M 这样的合并,假设您刚刚添加它,您通常需要 运行 git reset --hard HEAD^git reset --hard HEAD~。 (这两个做同样的事情,虽然一些命令行解释器使一个或另一个更容易输入:CMD.EXE 特别是让你输入 ^^ 而不是 ^ 所以 ~ 更容易。请注意,您可以但不必在 ^~ 之后添加 1。)

根据您用来查看提交的内容,您可能仍会看到新旧提交。在重置之后,您不应该再看到添加的合并提交:旧提交和新提交将是单独的“链”。

要更新 GitHub 或 Bitbucket 或其他托管站点,您必须强制它用新的和改进的提交替换旧提交。这里有两个选项:

  • 删除或重命名旧存储库,使其不再存在于托管站点上,或以其他名称存在。在托管站点上创建一个新的空存储库,并使用本地存储库中的 git push。您可能想使用 git push --mirror,它会自动推送所有分支和标签,但请注意,这也会推送所有远程跟踪名称,您可能 不想这样做。您可能需要 git push --all --tags.

  • 或者,使用 git push --force,也许再次使用 --mirror--all --tags

请注意,使用 git push --force,您将丢失托管站点上的备份,因此请非常确定您在此处拥有正确的提交集。 BFG 进行就地重写;其他一些存储库调整器,例如 git filter-repo,要求您 运行 在新制作的克隆上,这样您就不会损坏任何“正常工作”克隆,这样您就有了备份 .

在所有情况下,请考虑在执行任何操作之前进行个人备份。从您刚刚制作的个人备份中恢复几乎总是比从您希望上周制作的某些标准备份中恢复更容易,但事实证明备份系统去年死了,没有人抽出时间来恢复修复它,因为一切都很好,你为什么要问?