可以撤销文件的永久删除吗?

Possible to undo permanent deletion of file?

我的一位同事试图从我们的 GitHub 存储库的历史记录中永久删除一个文件 (Diff.java)。

他有充分的理由想要这样做,但是似乎出了点问题,因为我们似乎丢失了相当多的文件,这些文件已被后缀为 .REMOVED.git-id 的等效文件所取代。例如 ivy-2.2.0.jar -> ivy-2.2.0.jar.REMOVED.git-id.

我已经设法修复了主开发 b运行ch,因为我碰巧在本地有一个副本。然而,有许多开发线的历史 bches 和发布的标签现在似乎以上述方式被破坏。

我了解到他 运行 的过程类似于:

$ git clone --mirror git://example.com/some-big-repo.git
$ java -jar bfg-1.12.3.jar --strip-biggest-blobs 500 some-big-repo
$ cd some-big-repo
$ git reflog expire --expire=now --all && git gc --prune=now --aggressive
$ git push

$ cd ..
$ java -jar bfg-1.12.3.jar --delete-files Diff.java some-big-repo
$ cd some-big-repo
$ git push

我猜这个过程是破坏性的,并且没有办法恢复,除非我们碰巧在发生这种情况之前的某个地方有一个干净的镜像。任何人都可以确认或提供一些建议吗?

这是删除所有旧 jar 的步骤:

$ java -jar bfg-1.12.3.jar --strip-biggest-blobs 500 some-big-repo

...作为 BFG 的作者,我很难过地意识到 --strip-biggest-blobs 500 并不像我想象的那么清楚。该命令从存储库历史记录中删除最大的 500 个文件(即大文件或二进制大对象:'blobs')。我很想知道用户认为该步骤会做什么!

这是正确删除 Diff.java:

的命令

$ java -jar bfg-1.12.3.jar --delete-files Diff.java some-big-repo

instructions for the BFG 在 运行BFG 之前对你的存储库说 "you should make a backup",但听起来这并没有发生在这里.

如果有两件事,您可能仍有机会恢复旧的分支和标签:

  1. 原始对象数据仍然可用的存储库。那将是您的本地副本,也可能是 GitHub,因为它们不会立即 运行 git gc 他们的 回购 - 对象可能很好仍然存在,甚至可能被旧的拉取请求引用,如果你使用它们的话。我会立即对您的 GitHub 存储库进行镜像克隆。
  2. 您还需要旧的 'ref' 值(原始分支和标记提交 ID)。您可以在本地副本的 reflog 或 CI 服务器的日志中找到它们。 BFG 在命令行上打印出更改后的引用的旧值和新值,但我猜你仍然没有那个输出。 BFG 当前不保存该输出,但它 每次 运行 时在 some-big-repo.bfg-report 目录下保存一个 object-id-map.old-new.txt 文件,其中包含旧 ID 和新 ID,每次提交都会更改。这些文件将不止一个,因为 BFG 不止一次 运行。使用这些文件,并检查你的 current refs,你应该能够通过两个 BFG 运行s 回溯以找出你的 refs 的原始提交 ID 是什么.

考虑到这些,您的恢复过程是这样的:

  • 对您的存储库进行 --mirror 克隆,最有可能仍然包含您的旧对象。
  • 测试它是否真的有那些对象。因此,假设您可以确定 master 的旧 ID 是 686b0cd80ac328e060b80dda3c9dadb1e400134a,请执行 git cat-file -p 686b0cd80ac328e060b80dda3c9dadb1e400134a。如果对象仍然存在,您将看到提交摘要。如果不是,请为您的其他候选存储库添加遥控器,并尝试从那里提取数据
  • master 分支设置为 git update-ref 原始提交的值:git update-ref refs/heads/master 686b0cd80ac328e060b80dda3c9dadb1e400134a

重复您关心的所有其他分支和标签 - 希望您可以编写脚本,祝您好运!