合并同一项目的两个git存储库,链接文件历史记录

时间:2018-11-09 00:58:47

标签: git github merge git-merge

我有一个很久以前开始的项目,并进行了很多提交。然后该项目被放弃了大约两年,在此期间我忘记了我一直在该项目上使用git版本控制。我拿起它,将所有文件复制到一台新机器上,并用约100,000行代码和数十个文件开始了一个新的git repo,该文件现在具有自己的漫长提交历史。我最近重新发现了旧的仓库,并试图将两个仓库的提交历史合并在一起,using the instructions here.

但是,结果不完整。如果我查看github上的提交历史记录,则来自旧存储库和新存储库的提交都是完整的,但是每个文件的历史记录都不会扩展到旧存储库的一系列提交,仍将它们显示为在创建时进行的简单创建新存储库。手动复制所有内容以启动新存储库时,有几个文件没有传输。

自旧存储库的历史记录结束以来,该项目的文件结构和命名约定已发生了显着变化,并且某些文件关联可能并不明显。如果必须一次手动将旧的与新的链接,则可以这样做,但是自动解决方案会更好。

1 个答案:

答案 0 :(得分:1)

我假设您已按照从顶部答案到所链接问题的步骤进行操作。这些不是解决这种情况的最佳步骤。

您的项目有两个历史段。如果我们假设第一段有提交

A -- B -- C <--(master)

第二段有提交

D -- E -- F <--(master)

然后,行为如预期的完整历史记录如下

A -- B -- C -- D' -- E' -- F' <--(master)

(关于符号的注释:在合并的历史记录中,我已将D替换为D'等。其原因可以说是技术性的,可能不是立即重要的;总而言之,这仅意味着就提交身份而言,D'D是不同的,因为D'C为父,而D没有。相同,以表明D'代表与TREE相同的代码状态-即相同的内容或D-)。

您链接的答案无法实现。它满足了两个最基本的目标-将提交放入一个回购中,然后将它们组合成一张图-但它不符合最有价值的一个:对它们进行连贯的历史记录。相反,它给了你

   A -- B -- C
              \
D -- E -- F -- f*

其中f*是合并提交(即具有多个父项的提交),其内容与F相匹配,但同时也将C列为其历史记录的一部分。

与此有关的问题是,C不是 ,然后被识别为D历史的一部分。实际上,git的默认历史记录过滤规则(例如,用于日志输出)将完全排除ABC,因为从git的角度来看,可以解释代码的状态没有他们。

(关于您问题的当前评论中,大多数谈论相似性启发式方法的人都是红鲱鱼。在我看来,这些评论是由并未真正仔细观察您所遵循步骤的人们写的。 )

有两种方法可以达到所需状态。如果这是仅您使用的存储库,或者可以与所有存储库用户协调以进行历史记录重写,那么“重新父项”操作将是一个很好的解决方案。这是一个永久性修复程序,可以创建无缝的历史记录;但是,由于它将改变当前回购分支的历史,因此与任何其他用户的协调非常重要。 git rebase文档中有关“从上游资源恢复”中的部分通常描述了重写共享历史记录的问题。

另一种替代方法是使用git replace。这样做的好处是,它不是历史记录重写,但是确实存在一些已知问题,并且每个克隆都需要进行一些特殊的设置。 (如果未完成设置,则意味着特定的克隆看不到完整的历史记录。)

这是一篇讨论这些方法的帖子:Git: Copy history of file from one repository to another

还有其他变体,很难说哪种最适合您的情况。如果您想更广泛地探索各种可能性,则可以查阅git filter-branchgit replace的文档。