在主设备硬复位后是否可以再次合并分支?

时间:2016-04-20 08:37:34

标签: git github merge

这是我的情况。我掌握了一个master分支,dev1和dev2分支。现在我已经将dev1快速转化为主人。之后,我也将dev2合并为master。

现在,快进合并实际上是偶然的,因为我想提交一个提交消息。

现在我知道我可以使用git reset -- hard <hash of commit before any merge>进行硬重置,然后强制push to master重写历史记录。

我的问题是,在完成所有这些之后,我是否仍然可以通过自定义特殊提交将dev1和dev2分支再次合并到master中?

以后会不会有任何问题,master会再次合并到dev1作为master的副本,我可以在哪里进行新的更改?

1 个答案:

答案 0 :(得分:1)

对于所有历史修改,这个问题的答案是&#34;它取决于&#34;。 comment from Useless包含正确的问题:还有其他人有这个吗?

在这种特殊情况下,&#34;这个&#34;部分 - 我们关注的是其他人可能拥有的东西 - 实际上可能比其他强制推动案例更重要(尽管仍然稍微重要)。原因是快进合并根本不是合并,而只是标签动作。

绘制图表

让我们绘制提交图。每当我们在git中遇到一个困难的情况时,&#34;绘制提交图&#34;几乎总是正确的第一步。

  

我掌握 [我认为这意味着&#34;制造&#34;或&#34;有#34; ...?] 主分支,dev1和dev2分支。

所以:

... - o - o           <-- master
           \
            o - o     <-- dev1
                 \
                  o   <-- dev2

我在这里猜测有多少提交节点以及这是否是一个好用的形状。如果绘制图形,这将有很大帮助,因为你实际上有了存储库,因此可以绘制一个正确的存储库。但无论如何:

  

现在我已经快速将dev1转变为主人。

我猜这就是你的意思:

$ git checkout master && git merge dev1

并且git告诉你,它做了一个快进。如果这是真的,那么master上的任何提交都不应该在dev1上,所以至少部分绘图必须是正确的。结果如下:

... - o - o
           \
            o - o     <-- dev1, HEAD->master
                 \
                  o   <-- dev2

也就是说,dev1master都指向相同的提交(哈希2199c3a...或其他)。我在HEAD->前添加了master,因为我们在分支主机上(通过git checkout master)。

(我们可以重新绘制图表,但不包含小狗腿洞,但即使第一行上没有标签,我们也可以让它向下和向右移动。)

  

之后,我也将dev2合并为master。

你没有说这是否也是一个快进行动。如果您没有使用任何标记并且上面的图表是正确的(或足够接近),那么它将是,结果将是:

... - o - o
           \
            o - o     <-- dev1
                 \
                  o   <-- dev2, HEAD->master

换句话说,这些快进操作中的每一个 - 根本没有合并 - 只是向前滑动master标签(因此名称&#34;快进&#34;)。 / p>

现在我们来看看你是否推动了这一切。

如果您没有推送任何内容,那么您的状态良好,因为您的存储库是唯一一个有任何更改的存储库。

如果推送它,请查看您推送的新提交内容。最终图形中哪些提交节点不在原始图形中?

通过眼球比较这两个图表几次,并且因为我们没有理顺狗腿而感到高兴。 : - )

这里的事情是我们已经添加了任何提交,因此即使你已经推送了这个提交,也没有提交删除的提交。成功的git push唯一能做的就是说服接收存储库的git将其master分支移动到与dev2相同的节点。

假设上述内容都是准确的(或足够接近):如果我们倒回并进行真正的合并会发生什么?

首先,让我们通过将git reset --hard <commit-id>标签回到顶部来模拟master,再次给我们第一张图:

... - o - o           <-- HEAD->master
           \
            o - o     <-- dev1
                 \
                  o   <-- dev2

现在让我们做一个git merge --no-ff dev1来建立一个真实的实际合并节点。再次,绘制图表:

... - o - o ----- o   <-- HEAD->master
           \     /
            o - o     <-- dev1
                 \
                  o   <-- dev2

现在让我们进行另一次真正的合并,git merge --no-ff dev2(这次实际上并不需要--no-ff,但让我们使用它来保持意图的一致性和清晰度):< / p>

... - o - o ----- o - o   <-- HEAD->master
           \     /   /
            o - o <-/-------- dev1
                 \ /
                  o       <-- dev2

dev1仍然指向同一个地方;我刚开始在页面上没有空间,所以我尽力把它画得相当清楚。)

如果我们从未将master更新推送到任何地方,显然没有其他人知道我们做过任何事情,我们可以安全地推动它。

如果我们确实推动了怎么办,但到目前为止所有绘制的内容都足够接近?

假设我们已经git push 现在,在远程已经master指向与dev2相同的提交之后?现在有两种可能性:

  1. master仍然指向与dev2相同的提交。我们将要求远程快进名称master以指向我们的第二次合并提交。这个快进,因为我们的第二次合并提交有两个父提交。它的第一个父是我们的第一个合并提交,它的第二个父是dev2指向的提交。因此,遥控器将允许这作为常规(非强制)推送!

  2. 其他人添加了一个新提交(或几个新提交)。好吧,现在我们遇到了一些麻烦,因为现在我们必须强制推送(丢弃提交并让它们重新工作),或者我们必须放弃我们的合并,拿起他们的东西,重新做我们的合并,我们在我们的分支机构中有点松懈,我们的合并父母不是我们想要的方式等等。也就是说,我们可能会在第一次合并后看到更像这样的图形:

    ... - o - o       ------- o   <-- HEAD->master
               \     /       /
                o - o   <---/-------- dev1
                     \     /
                      o <-/---------- dev2
                       \ /
                        o         <-- origin/master
    

    并尝试在第二次合并中绘制更糟糕(可能是时候废弃这个版本的图并重新开始:-))。

  3. 底线

    这取决于图表。画出你拥有的东西,画出你推向别人的东西,画出你想要的东西。看看在没有--force的情况下是否可以推送您喜欢的内容。