乌尔德女神作战计划——Git 历史修改

原本博客前端是有代码自动生成的,在一次进行 git 仓库镜像同步的时候,不小心把所有分支覆盖了。导致之前的的记录都没了(虽然并不影响啥)。
不过处于好奇,还是尝试恢复了一下,中间又误操作把顺序恢复反了。不过最终还是可以完美还原的


相关梗出自《命运石之门》,实验修改过去D-Mail作战计划(Operation URD)。乌尔德是北欧神话中诺伦三女神之一,掌管过去的时间。

寻找过去的世界线

如果世界线没有被当作垃圾回收,那么使用git reflog可以看到所有世界线(即使已经属于被遗弃的孤立世界线)

git reflog 记录git reflog 记录

通过该命令,可以查看到首次新的提交从2ff1061ef开始。那么从上往下,分别checkout到对应的节点查看历史即可

经过几次尝试,发现g'g为最后一次拉取的记录,因此还原从这里开始。

将该记录重新保留出来,用来操作
使用git checkout -b ref,新建ref分支指向当前位置(a062d8218)

合并世界线

使用git rebase可以合并两个分支的内容

这里使用git rebase gh-pages ref实际上这么做合并反了,不过为了后面的内容,先这么写)

合并后,会发现 git 的记录是先新版本(2021 年 2 月)再老版本(2020 年 2 月 ~ 2021 年 1 月),显然这不符合时间顺序。
因此,需要修改 git 的记录

逆转时间,重塑历史

万物皆可rebase,我们可以修改从头开始的所有 git 记录

通常,如果只需要修改 HEAD 前几条,使用git rebase -i HEAD~3,如果要修改到特定提交则是git rebase -i abcde

但是根记录是不会被计入这里的,如果我们直接选取当前最早的提交2ff1061ef,那么会实际上是处于2ff1061ef提交后的状态,而这个提交实际上也是需要修改的。

要修改所有提交,使用git rebase -i --root,这样就可以在交互界面里看到所有内容,把最上面的几行(最老的提交——新版本的记录),剪切到最下面几行(最新的提交)处。
这样,提交后就实现了对提交记录的修改

由于文件 diff 关系变化,所以这里实际上是重新模拟文件提交一次,由于是重新提交,所以哈希值会变化且时间可能会很慢,并且部分关键节点可能会要求二次确认。

重新确认提交内容重新确认提交内容

考虑到需要大量的重新提交,可以使用循环脚本实现

for ((i=0;i<100;i++)); do git add . && git rebase --continue; done

至此,时间女神被成功欺骗,我们重塑了历史

强制推回对应分支即可

参考资料