如何恢复一个fork的git历史记录,其中历史记录已被删除?

3
我有一个包含数百个提交的项目,它是另一个开源项目的分支。在创建分支时,git历史已被清除。现在我想重新附加历史记录。
原始项目有数千个提交,称为:A <- B <- C <- D 与此同时,我们的分支有:E <- F <- G <- H 这些分支没有共同的祖先,但提交DE具有完全相同的文件系统。创建E时,git历史已被清除。
如何在不解决合并冲突的情况下重新连接它们?
尝试过的解决方案:
- git cherry-pick fork/initial..fork/develop - 我尝试将更改从分支挑选到原始仓库,但结果出现合并冲突。该解决方案试图线性重放提交,但由于所有分支和合并的存在,一路上会出现合并冲突。 - git rebase -i fork/initial fork/develop~0 --onto new-branch - 与上述问题相同,rebasing而不是挑选也无法解决问题。它尝试按顺序重放提交,导致合并冲突。我还尝试使用--rebase-merges,但无济于事。 - git merge fork/develop --allow-unrelated-histories - 这是最接近我想要的。它仍然导致了大量合并冲突(出于我不理解的原因?),但我用git checkout fork/develop -- .git commit一次性解决了所有合并冲突。这种解决方案的问题在于分支的“初始提交”仍然是触及每个文件的最旧提交,因此我没有获得巩固这些分支的任何好处。
到目前为止,我遇到的所有解决方案都需要我解决冲突。这不应该是必需的,因为我试图在文件系统完全相同的点上附加历史记录。 我只想将历史记录重新附加到它来自的位置。有什么建议吗?

将 E 到 H 的提交衍合到 D 上? - matt
1个回答

3
你可以试试这个。
git rebase --onto D E H

应该将F、G和H放在D的顶部……不完全是这样。当然,那将是原始修订的副本。也就是说,假设E..H是一条直线。

更新

我创建了一个脚本,可以在另一个修订版的顶部复制分支历史记录,而无需像rebase那样进行任何cherry-picking。它使用原始修订版本的信息即时创建新的修订版本,当然包括合并。

https://github.com/eantoranz/git/blob/replay/contrib/replay

将它作为独立工具来使用,因此如果您想执行类似于 git rebase --the-real-deal --onto new-base old-base tip 的操作,您需要执行:./replay new-base old-base tip。从问题中给出的示例来看:./replay D E H。它在stdout中打印的单行是您要重播的tip相应修订版本的ID。


我对嫁接技术没有太多经验,但也许这是它们派上用场的情况之一? - eftshift0
1
是的,一个修订版本就是一个提交。 - eftshift0
只是为了澄清,我知道它生成了一个新的提交并没有改变工作树。我运行了 git log <new-commit> 并滚动到底部。提交 E 的哈希值没有改变,而其后代都有新的 ID。Git v2.35.1。 - Alex
刚刚推送了一个新的修复版本。如果我没有在旧基础和新基础之间添加映射,你最终会在旧基础上工作,因此并没有做任何有用的事情。 - eftshift0
你看到的错误...可能和标签有关吗?希望现在能运行得更好。告诉我(尽管我预计必须再次从脚本中移除断言...或者你正在克隆以便合并你的更改 :-)) - eftshift0
显示剩余13条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接