重写子模块历史后的子模块存储库

Repository with submodules after rewriting history of submodule

git filter-branch 重写存储库的历史后,所有 SHA 都发生了变化。

现在,如果该存储库(我们称之为 X)用作另一个存储库(我们称之为 Y)中的 git 子模块,我们就会遇到问题。
事实上,Y 知道根据该子模块中提交的 SHA 加载哪个版本的子模块 X。由于 X 中的所有 SHA 现在都已更改,因此 Y 指向不再存在的 SHA。

有没有办法重写 Y 的历史,使其指向子模块 X 的新提交 SHA(包括当前和过去的提交)?

我猜想鉴于旧 SHA 和新 SHA 之间的对应关系,这在原则上是可能的,但我担心它会涉及讨厌的 bash 脚本。
有没有更简单的?

but I am afraid it would involve nasty bash scripts.

恐怕是的。

Is there anything easier?

据我所知没有。
以下是该脚本运行所需的一些线索(不是完整的脚本):

如果您仍然可以访问重写的回购协议,其原始历史记录(过滤器分支之前)保存在.git/refs/original

这意味着您可以循环查找旧历史 SHA1:

 git -C /path/to/rewritten/repo for-each-ref --format="%(refname)" refs/original

如果更改仅限于一个分支,您可以轻松地将新 SHA1 与旧 SHA1 匹配(第一个旧的匹配重写分支的第一次提交,第二个旧的...等等)

如果没有,您将不得不寻找一个 revs 以找到匹配项(同一日期,合理的提交消息)

git rev-list --all \
  | while read commit
 do
 ...

确保父仓库更新了子模块的引用:

cd parent/repo
cd asubmodule
git fetch

这样,新的 SHA1 就可用了。

最后,您可以在父存储库中执行过滤分支,查找 gitlink, special entry in the index,匹配旧 SHA1 之一。

对于每个匹配项,您在子模块文件夹中检出新的 SHA1,返回到父存储库的上一级,添加并提交:这将记录一个新的 gitlink SHA1。

cd parent/repo/asubmodule
git checkout <new SHA1>
cd ..
git add .
git commit -m "Record new SHA1 for asubmodule"