这是我的情况。我掌握了一个master分支,dev1和dev2分支。现在我已经将dev1快速转化为主人。之后,我也将dev2合并为master。
现在,快进合并实际上是偶然的,因为我想提交一个提交消息。
现在我知道我可以使用git reset -- hard <hash of commit before any merge>
进行硬重置,然后强制push to master重写历史记录。
我的问题是,在完成所有这些之后,我是否仍然可以通过自定义特殊提交将dev1和dev2分支再次合并到master中?
以后会不会有任何问题,master会再次合并到dev1作为master的副本,我可以在哪里进行新的更改?
答案 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
也就是说,dev1
和master
都指向相同的提交(哈希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
相同的提交之后?现在有两种可能性:
master
仍然指向与dev2
相同的提交。我们将要求远程快进名称master
以指向我们的第二次合并提交。这个是快进,因为我们的第二次合并提交有两个父提交。它的第一个父是我们的第一个合并提交,它的第二个父是dev2
指向的提交。因此,遥控器将允许这作为常规(非强制)推送!
其他人添加了一个新提交(或几个新提交)。好吧,现在我们遇到了一些麻烦,因为现在我们必须强制推送(丢弃提交并让它们重新工作),或者我们必须放弃我们的合并,拿起他们的东西,重新做我们的合并,我们在我们的分支机构中有点松懈,我们的合并父母不是我们想要的方式等等。也就是说,我们可能会在第一次合并后看到更像这样的图形:
... - o - o ------- o <-- HEAD->master
\ / /
o - o <---/-------- dev1
\ /
o <-/---------- dev2
\ /
o <-- origin/master
并尝试在第二次合并中绘制更糟糕(可能是时候废弃这个版本的图并重新开始:-))。
这取决于图表。画出你拥有的东西,画出你推向别人的东西,画出你想要的东西。看看在没有--force
的情况下是否可以推送您喜欢的内容。