恢复git合并提交类型

时间:2017-12-06 06:30:34

标签: git

THIS问题中,我询问{{ original }} <br> {{ translate }} <br><br> <a href="{% url 'home' %}">Home</a> git merge branchname之间的区别以及它对项目历史的影响。现在跟进:
是否可以在将此分支推送到远程后更改此合并提交类型(来回git merge branchname --squash? 背景故事当然是我与错误的旗帜合并,现在是时候自己清理......

1 个答案:

答案 0 :(得分:1)

简短的回答是否定的,除非通过强制推动。

要理解为什么,请考虑以下事实:在Git中, merge 一词充当动词,合并,同时也充当形容词或名词:合并提交(提交类型&#34;合并&#34;)或合并(合并提交)。

当我们使用动词形式来合并时,我们的意思是组合两个不同的变更集合,这些变化是针对某些常见的基础进行的。这是git merge(进行真实,非快进,合并时) git merge --squash的动词形式。所以在这一步,两者的行为方式相同。 (到目前为止,我们还不错。)

git mergegit merge --squash完成&#34;合并&#34;但是,它们采取了两种不同的路径。正常的非压缩合并会生成合并提交,这是一个具有两个父提交ID的提交。通过运行--squash - 正常的单父提交,git commit合并会让您更好地做出决定。无论哪种方式,您都会获得提交,但关于Git提交的事情是它由哈希ID 唯一标识,并且其哈希ID由中的每一位信息确定>提交。至关重要的是,这些信息包括父哈希或哈希值。

这意味着,当你或Git发表这篇文章时,&#34;合并为动词&#34;提交,你冻结提交的ID,两个父项(如果是合并提交)或单个父项(如果是正常的非合并)。与每个 Git对象一样,一旦根据内容计算哈希ID,就无法更改哈希ID和内容的配对。如果您更改了内容,则会创建一个 new 对象,该对象会获得(和不同的)ID。

因此,您可以在git push之前进行提交,使用相同的树进行新的提交,但只使用一个父级或父母双方 - 无论哪一个都没有时间周围 - 因此,真的,真的,合并提交&#34;和&#34;并非真正合并壁球提交&#34;存储库中的对象。然后,您可以选择其中一个并将其发送到某个远程,并要求远程设置其自己的名称,例如masterdevelop或远程上的任何名称,以指向一个提交

但是现在,您已经将这两个哈希ID中的一个发送到远程,并要求它将其名称设置为指向一个提交。让我们说,具体来说,您要求遥控器设置名称M。您可以发送其他哈希ID(如果您愿意,可以先进行其他提交),并要求远程设置一些其他名称,例如N,以指向其他哈希ID;一般来说都可以。但是,如果您要求远程设置M到另一个哈希ID,则远程首先会查看M当前设置。它会看到使M指向新提交而不是旧提交实际上丢失旧提交,因为新提交的哈希ID没有旧提交在其祖先中提交哈希ID(新提交的哈希ID不是M的当前哈希ID,也不是新提交的父级或父级M ,他们的父母也不是M,等等。

因此,远程&lt; remote&gt;将拒绝git push <remote> <hash>:M作为非快进。要让其他Git将其M设置为新哈希,丢弃旧哈希,必须向其发送强制推送操作。这并不保证遥控器会服从,但它确实告诉遥控器你想要从他们的M中丢弃一些提交。

这里的危险是:

  • 您可以放弃先前推送的提交(这是您的意图),转而支持您的新哈希(这样更好),但也许其他人已使用该远程选择了您的旧的合并,所以现在它已经在互联网上传播。这给每个人带来了问题。

  • 您可能会丢弃 more 而不仅仅是您推送的合并。假设Bob在该提交上添加了一个提交,并且Carol在Bob的上面添加了一个提交。你的强制推送将丢弃你的旧提交以支持你的新提交,但它会丢弃在旧提交之上构建的Bob和Carol的提交。

如果您确定Bob和Carol不存在并且没有其他人拥有您的旧(错误合并样式)提交,那么它足够安全以强制推送该提交并将其替换为改进了一个。但如果没有,它毕竟不安全。您可以查看--force-with-lease选项作为替代选项,但如果其他人选择了您的错误提交,则该错误提交可能会继续返回,类似病毒,会困扰您。