我可以通过一种新的上游存储库将其合并的方式添加到我的存储库吗?

时间:2018-09-18 15:26:31

标签: git gitlab

我们有一个基于某些第三方代码的本地项目。不幸的是,我们的本地版本最初是基于第三方代码的压缩文件设置的,并存储在SVN中。随着时间的流逝,它也随着来自第三方的更改而更新(通过一些激动人心的三向diff活动)。

我们的本地代码已迁移到GIT(使用GitLab作为中央存储库)。鉴于GIT中也提供了第三方代码,我希望可以将两者集成在一起,并有效地将第三方存储库作为本地存储库的上游。

我天真的想法是克隆我们的本地存储库。然后将第三方作为上游添加到我的沙箱中。然后,我可以从上游执行合并到我的主服务器。 (这可能来自上游的分支,因为我们要落后一两个版本)。我可以将其推送到我们的存储库中。

但是,如果我是对的,那么这似乎只会推动我合并的主服务器,而不会推动上游的存在?我们将如何将上游添加到我们的中央存储库中?如果这样做,那么我们如何执行合并?克隆仓库时,我们是否也可以有效地克隆上游?

我期望初始集成(合并)非常繁琐,因为两个存储库实际上没有共同的祖先。不过,我希望继续进行后续合并会简单得多,并且不必从头开始有效地进行重新合并。

摘要:给定两个未连接的GIT存储库,它们实际上包含相同源代码的两个(修改的)版本,如何添加一个作为另一个的上游?

1 个答案:

答案 0 :(得分:2)

  

摘要:给定两个未连接的GIT存储库,它们实际上包含相同源代码的两个(修改的)版本,如何添加一个作为另一个的上游?

像这样设置上游很简单。使得图 connect 并非如此:您只会在自己的存储库中获得两个不相交的子图。

请记住,Git与 commits 有关。提交具有哈希ID,这些较大的丑陋哈希ID是提交的实际名称。每个提交都存储其父提交的哈希ID。诸如master之类的分支名称或诸如v1.0之类的标签名称只是进入图中并使提交 reachable 的方式,这样它们才不会被Git的垃圾收集器吞噬。有关背景,请通读网站Think Like (a) Git

请注意,提交的哈希ID是该提交内容的低温校验和。内容包括树哈希和父哈希。这意味着图本身就像Merkle Tree,因此可以验证整个历史记录,但这也意味着您不能更改任何提交的哈希ID。

因此,当您将一个不相关的(按图显示)存储库并将其猛拉到自己的存储库中时,会发生以下情况:

your-root--o--...--o   <-- your-master
               \
                o    <-- your-branch


              o--...--o   <-- their-branch-X
             /
their-root--o--...--o---o--o   <-- their-master
             \         /
              o--...--o   <-- their-branch-Y

没有常见的提交-存储库是独立创建的 ;它们不仅从某个通用克隆开始,然后又发散,所以您的根提交与其根提交也不相关。

这使得进行合并基本上是不可能的。

有一个 解决方案,即将两个图嫁接在一起。可以说,由于某些巧合,两个词根具有相同(或足够接近)的 snapshot ,因此,如果我们在前面添加“超级词根”,则事物可以合并:

        your-root--o--...--o   <-- your-master
       /                \
      /                 o    <-- your-branch
     /
super
     \
      \               o--...--o   <-- their-branch-X
       \             /
        their-root--o--...--o---o--o   <-- their-master
                     \         /
                      o--...--o   <-- their-branch-Y

但是,我们现在遇到了Merkle树问题:如果从字面上添加此节点,则必须复制 all 个下游节点,即您的所有commit 他们的所有承诺。通过复制(但更改某些内容)每个原始文件而进行的这些新提交将具有新的和不同的哈希ID。

我们可以使用git replace来更形象地添加节点。确实确实将超根节点添加到了您的存储库中,但实际上并没有使其成为两个现有根的父级。取而代之的是,我们创建两个替换根提交,以超级根作为父提交,并指示Git“旁观”替换。此方法是可行的,但有一个缺点:默认情况下,克隆此存储库不会获得替换对象。 (您也可以专门要求它们,然后克隆的行为与带有替换项的存储库的行为相同。)

如果拥有“上游”存储库的任何人都愿意重写其所有历史记录,而您又愿意重写所有历史记录,那么也有解决方案。如果他们不愿意重写所有历史记录,只要他们的历史记录至少与您关心的一样深,仍然有可能的解决方案:您可以重写所有您的历史记录,以其作为基础他们的所有历史记录,并删除您所缺少的任何较早的历史记录。

这些都不是很有趣,但是它们都可以使用git replace进行构建和测试,以将两个不相交的图嫁接在一起(使用这些替换的“虚拟提交”)。一旦有了适合所有人使用的图形,请运行git filter-branch将虚拟图形转换为新的不同物理图形。所有具有新历史记录的提交都将获取新的唯一哈希ID,现在您可以使每个人都切换到新存储库,而不是旧存储库。