同步两个单独的Git回购

时间:2018-05-10 11:10:23

标签: git

我们必须处理另一个团队回购,但出于各种原因,我们希望保持我们的开发工作不被看到,直到它准备推送到他们的回购。

我克隆了他们的repo,删除了.git文件夹,然后用文件创建了一个新的repo。这让我们起步并运行,但我不确定现在是将更改从其回购合并到我们的回购的最佳方式。

有没有更好的设置,我们可以孤立地工作,但没有在合并之上有这么尴尬的时间?

2 个答案:

答案 0 :(得分:1)

删除.git是不利的。

再次克隆远程仓库。您可以添加其他遥控器 git remote add yourrepo http://urlOfYourRepo

确保将不同步分支的默认推送/提取回购设置为yourrepo:git push -u yourRepo以设置默认上游

您可以随时git fetch origin对您的回购进行远程回购更改,然后将其合并到您的回购中。

使用git push origin yourCommit,您可以将您的提交(或分支)推送到远程仓库。

答案 1 :(得分:1)

删除.git文件夹后,您删除了历史记录。然后通过从这些文件创建一个新的repo,你开始了一个新的历史记录,在git的视图中,它是无关的。即使您在进行任何更改之前已提交,仍然会创建提交(内容完全相同)。

你想要的是你的团队的回购保留上游回购的历史记录,以便你的回购知道你的变化与历史相关,然后它(相对)容易合并上游变化。然后,您只需控制推送到该原点的内容即可控制上游可见性。

这仍然可以实现,但确切的步骤取决于有关您当前状态的一些问题。我将不得不做出一些假设,所以请评论这些假设是否错误,我可以尝试相应地调整答案。

所以大概是你创建了一个新的仓库,你有一个名为origin的远程开发人员,你的开发人员可以从中克隆他们的本地仓库。 (继续前进,我将调用origin,以及您从中获取第一个快照的原始存储库,我将调用upstream。)

我还假设您的origin中正在进行积极的开发,因此仅从clone重新upstream就会出现问题。并且您正希望将upstream的更改集成到origin

第一步,使用origin的克隆进行操作,即可获取upstream历史记录。

git remote add upstream url/of/upstream/repo
git fetch upstream

接下来,您需要整合历史记录。有几种方法可以做到这一点。最好的长期结果来自历史重写,但需要您的团队之间进行一些协调。

理想情况下,您会告诉团队中的每个人push他们的工作是origin;它不需要完全合并,但所有分支都需要push。在push工作之后,他们应该丢弃他们的克隆并等待你告诉他们重写完成,此时他们会创建origin的新克隆(并且,可选地,添加{{ 1}}遥控器。)

如果这种协调水平不可能,仍然可以进行重写;但是对于部分或全部开发人员来说可能会有更多的工作,因为他们必须在upstream origin时执行他们自己的迁移clone fetch } d(或在重写之前完成了你的最后fetch)。在这种情况下,最好使用非重写选项(稍微多一点)。

upstream编辑您队伍的所有历史记录(或在克隆您的工作回购时复制它),接下来需要在origin历史记录中确定与您的master存储库中的初始提交。

如果这是标记版本,那可能会使事情变得简单;但我假设它只是当时git diff上的任何内容。但即使在这种情况下,如果您知道何时执行此操作,您应该能够跟踪正确的提交并通过O验证它是否与您的初始提交相匹配。

所以你找到了提交,我们在下图中标记X -- X -- O -- X -- X -- X <--(upstream/master) o -- A -- B <--(master)(origin/master) \ C <--(someBranch) ;为方便起见,您可能想要标记它。

o

现在,最简单的做法是重新父母O,以便替换它的父母A。另一个选择,产生一个&#34;清洁&#34;结果,是重新父Co,将O替换为 git filter-branch --parent-filter "sed \"s/$(git rev-parse master~2)/$(git rev-parse origin/master~3)/g\"" -- --branches 作为其父级。后者可能稍微复杂一点,但没有你想象的那么多;所以让我们来看看如何做到这一点。在上面的示例中,您可以使用类似

的内容
X -- X -- O -- X -- X -- X <--(upstream/master)
          |\
          | A* -- B* <--(master)
           \
            C* <--(someBranch)

o -- A -- B <--(refs/original/refs/heads/master)(origin/master)
 \
  C <--(refs/original/refs/heads/someBranch)

应该给你

git push -f

然后,您可以强制推送(origin)所有重写的分支到origin,或者从新的回购中重新创建original/refs/heads

请注意,您进行重写的本地仓库将在origin下有新的refs,表示分支的预重写位置。另请注意,origin的远程跟踪引用尚未更新(直到您执行强制推送,或直到您删除origin远程并使用反映重写的远程重新添加它。

那么......如果你决定重写怎么办?那么,在这种情况下,您可能希望拥有一个&#34;集成回购&#34;,从upstream克隆并添加git replace。在集成仓库中,您将设置o映射,告诉git&#34;每当遇到对象O时,请使用对象git replace代替&#34;。这篇&#34;论文超过&#34;问题。它可能有一些怪癖(请参阅replace文档),但理想情况下,您可以在一段时间过后停止依赖X -- X -- X -- O -- A -- B -- C <--(upstream/master) o -- D -- E <--(master) 映射(和集成存储库)。开发者&#39;历史不会像重写一样干净,但是没有必要切换到重建的存储库。

这里的想法是,最终历史将足够组合&#34;如果没有替换,git将会理解该怎么做。这将与如何计算合并基数有关。考虑一个简单的案例。

upstream

现在您要将master更改合并到git replace master~2 upstream/master~3 。在您的集成回购中,您已经说过

X -- X -- X -- O -- A -- B -- C <--(upstream/master)
               :
               o -- D -- E <--(master)

我们可以画成

X -- X -- X -- O -- A -- B -- C <--(upstream/master)
                 \
                  D -- E <--(master)

默认情况下使用git命令&#34;请参阅&#34;

git checkout master
git merge upstream/master

如果你说

的意思
O

计算出的合并基数为X -- X -- X -- O -- A -- B -- C <--(upstream/master) \ \ D ---- E ---- M <--(master) ,git将&#34;认为&#34;它给你了

X -- X -- X -- O -- A -- B -- C <--(upstream/master)
               :               \
               o --- D --- E --- M <--(master)

真的是

master

在此示例中,upstream是唯一接收master更改的分支,此时upstream/master的历史记录会追溯到upstream/master;因此,下次将master合并到C时,合并基础应为X -- X -- X -- O -- A -- B -- C <--(upstream/master) \ o --- D --- E --- M <--(master) ,并且不再需要替换(因此可以在任何克隆中执行,而不是需要进行在一个特别设置的整合回购中。)

现在我提到开发人员&#39;历史不会像&#34;清洁&#34;,显而易见的是,在你停止使用替换后的最终状态,我们有

D

所以&#34;血统&#34; EMM的某些内容有所不同。特别是CE合并到{{1}}中的结果并不明显。这可以被看作是一个邪恶的合并&#34;,虽然它没有那些在某种意义上的默认合并(不使用替换)会产生合并冲突。