撤消git中的合并并使用rebase

时间:2017-05-08 15:50:59

标签: git git-merge git-rebase

我们说我有这张图:

A - B -  C1.1 -  D - E - F -G (master)
       \_ C2.1 _/(feature)

我想撤消合并,将类似C1.2的内容添加到主分支,然后重新合并并应用D,E,F,G。我知道通常的方法是使用-m1标志恢复合并,然后在我们想要重新合并时恢复恢复提交(让我们假设我们不想挑选E,F, G,因为合并后可能还有更多提交。问题是:

为什么:

$ git resset --hard C1.1
$ git commit C1.2 # New commits here
$ git merge feature
$ git rebase G E --onto master

是不是在努力解决这个问题?要明确,"解决问题"有这样的图形(尽管提交的SHA值不同但内容相同):

A - B -  C1.1 - C1.2  - D - E - F -G (master)
       \_ _ _ C2.1 _ _ _/(feature)

3 个答案:

答案 0 :(得分:1)

在所有其他事项之前,请确保我们清楚了解提交身份。 (你的帖子暗示你已经意识到了这一点,但是你的图表有误导性。)如果你进行rebase,那么你正在创建新的提交,并且最多你的rebase将指向新的提交。 (如果你不使用分支引用作为rebase,那么只有HEAD最终会引用新的提交,这些提交本质上是临时的,除非你然后标记或分支给它们一个ref。)

让我们逐步完成您的程序。我们有

A - B - C1.1 - D - E - F -G <--(master)
      \      /
        C2.1 <--(feature)

所以我假设您已经master了,而且您说

git resset --hard C1.1

给了我们

A - B - C1.1 <--(master)
     \       \
      \        D - E - F -G
       \     /
         C2.1 <--(feature)

请注意,DG仍在那里(事实上你的后续命令依赖于它)。然后你做一些新的提交

git commit #c1.2

给出

A - B - C1.1 - C1.2 <--(master)
     \       \
      \        D - E - F -G
       \     /
         C2.1 <--(feature)

现在重新合并功能。

git merge feature

这是您创建新提交的第一个地方,但您的图表显示您可能会认为您已经某种程度地重新使用&#34;一个旧的。你真的有

A - B - C1.1 - C1.2 ------------ D' <--(master)
     \       \                  /
      \        D - E - F -G    /
       \     /                /
         C2.1 --------------- 
            ^--(feature)

接下来你的rebase语法错误。上游在提交引用之前(通常是分支),并且我认为 --onto可能必须在它们之前进行。此外,上游将是最后一次提交而不是重新设置,所以你真的想要像

这样的东西
git rebase --onto master D G

给出了

                                   E' - F' - G' <--()
                                  /                 ^HEAD
A - B - C1.1 - C1.2 ------------ D' <--(master)
     \       \                  /
      \        D - E - F -G    /
       \     /                /
         C2.1 --------------- 
            ^--(feature)

请注意,这并不会更新master参考号,因此接下来您需要执行类似

的操作
git branch -f master

从这里起,我将省略原始的DEFG,但他们仍然存在。特别是他们仍然在遥控器中(假设您有遥控器),并且仍然可以从远程版本的master访问。这意味着要推送,您必须强制推送&#34;这将使得repo处于问题状态,对于任何其他开发人员。参见&#34;从上游rebase恢复&#34;在git rebase文档中了解详细信息;如果这仍然是个好主意,那么push命令将是git push -f。那时,我们不再关心旧的提交,并且可以假设他们最终会被gc丢弃。

所以我们的图表将是

A - B - C1.1 - C1.2 - D' - E' - F' - G' <--(master)
     \               /
      C2.1 ----------
         ^--(feature)

D' ... G'是新提交;任何标记都不会被转移,任何其他分支仍然会指向旧标记,并且SHA1值(提交ID)将会更改。当你重写历史时,由于git存储数据的方式,这是不可避免的。

答案 1 :(得分:0)

如果我做对了,我会:

  • 回到C1.1,挑选C2.1,然后挑选E,F和G:

git checkout C1.1 git cherry-pick C2.1 git cherry-pick D..G # D won't be applied so it's all fine

答案 2 :(得分:0)

阅读了你发布的rebase命令对选项意味着什么,我认为问题是你说 git rebase GE - 大师我认为应该是git rebase D G --onto master,因此实际上没有应用D,它从那里到G(换句话说,应用E,F和G)。至少,这是我从阅读https://git-scm.com/docs/git-rebase

得到的