如何修复一个应该领先于大师的分支,但落后了?

时间:2018-01-05 16:19:14

标签: git git-merge git-rebase

我有一个功能分支,它的所有提交都应该在master之前,但是当我尝试将master合并到我的功能分支时,如下所示:

(feature)$ git merge master

功能分支中的所有更改都将被删除。我也尝试使用 rebase ,但我一直得到相同的结果。

(feature)$ git rebase master
First, rewinding head to replay your work on top of it...
Fast-forwarded feature to master.
(feature)$ git checkout master
(master)$ git merge feature
Already up-to-date.

我只是git merge feature来测试 rebase 是否有效,它没有Already up-to-date.

就像某种程度上我的功能分支落后于主人,我不知道这是怎么发生的。可能是功能分支已合并到分支,然后使用新提交删除,但是当我完成功能分支时我想在将来部署它的时候将它添加到 master

我的问题是,如何在分支之前移动所有提交到功能分支的提交

或者,在执行g it merge master

后,我是否可以重新提交当前位于功能分支中的所有更改
  

C1(特征分支)< - C2(将主控合并到特征中)< - C3(重新投入C1)

注意:

  • 我试图解决的所有问题都在我的本地机器上。
  • 我在一个团队中工作。

更新

我弄清楚究竟发生了什么,有人从功能分支创建了一个新分支(功能-B ),而不是从创建一个分支分支,然后将 feature-B 合并到主分支中:

(feature)$ git checkout -b feature-B
...
...
...
(feature-B)$ git checkout master
(master)$ git merge feature-B
(master)$ git push

然后在找出问题后,同一个开发人员将 feature-B 的合并恢复为 master

3 个答案:

答案 0 :(得分:4)

  

...可能是feature分支合并到master分支然后用新提交删除

很可能就是这种情况。但请注意以下事项:

  • 所有提交只是一些源树的快照,加上一些元数据:具体来说,是谁做了这个提交的时间(两部分,"作者" - 编写它的人 - 和#34; committer",将其添加到存储库中的人,加上提交消息,加上提交的哈希ID,或者用于合并提交,两个或多个父提交。
  • 新提交永远删除任何内容。它只是添加提交。
  • 要了解任何两次提交之间的不同之处,您(或Git)会提取每次提交,然后比较两个快照。

当您说通过新提交删除时,您的意思是:有人创作了一个提交,通过合并feature分支来撤销所带来的每一项更改。

  

然而,当我完成feature分支时,我希望将来在某个时候将其添加到master,我想部署它。

这是真正的问题。 其他人已经添加了它,然后添加了一个新的提交,说:不,全部撤消。 Git现在确定(并且正确)已经添加了 和(因为添加了提交)正确的最终状态不能使用它

这对您来说意味着这些提交对您不利。他们已经已经添加,然后会对他们施加一个新状态,以支持他们所做的事情。您无法再次添加它们:它们已经在那里。 您需要的是新提交,或恢复还原。

在这里,你很幸运。请参阅Re-doing a reverted merge in Git(问题和J-16 SDiZ's answer),然后另见Linus Torvald's article on the general topic of faulty merges,特别注意附录:使用原始版本重新创建主题分支(使用原始版本(现已恢复)提交。

答案 1 :(得分:2)

我担心你使用的某些非标准术语可能会让我对这个问题的理解蒙上阴影。但是,您建议几次将分支“可能已经”合并到master中,然后在master中撤消其更改。这可能是这样的:

x -- O -- x -- x -- M -- W -- x <--(master)
      \            /
       A --- B -- C <--(feature)

这至少与您描述的行为一致。在这种情况下,某人过早地将feature合并到masterM),然后还原合并(W)以解决问题。问题是,这使得git认为feature中的master中的更改永远不会

(这是记录在案的行为,但我认为这最初是一个意想不到的结果;底线是,featuremaster之间的任何未来合并都会将C视为合并基础;所以将feature合并到master只是一个快进(或者无论如何都不包括ABC所做的更改),以及将master合并到feature会将W的“还原”更改带到功能分支上(从AB和{{撤消所有工作1}},正如你所观察到的那样。)

解决此问题的一种方法是告诉git从新提交中重新创建C分支。例如,如果你说

feature

这会给你

git rebase -f `git merge-base feature master` feature

现在,如果您尝试在 A' -- B' -- C' <--(feature) / x -- O -- x -- x -- M -- W -- x <--(master) \ / A --- B -- C feature之间进行合并,则合并基数将为master,您将获得预期的结果。

当然,如果O已被推送到遥控器,则后续尝试推送feature将被拒绝(非快进移动参考)。你可以强行推送

feature

但是你必须与repo的所有其他用户协调以清理他们的本地副本(参见“从上游rebase恢复”下的git push -f 文档)。

如果这种清理/协调是一个问题,还有另一种选择:你可以“恢复还原”。这有点乱,但是再次从

开始
git rebase

你会

x -- O -- x -- x -- M -- W -- x <--(master)
      \            /
       A --- B -- C <--(feature)

现在你有了

git checkout feature
git merge master

由于x -- O -- x -- x -- M -- W -- x <--(master) \ / \ A --- B -- C ----------- M2 <--(feature) M2拉入W,因此feature上的工作似乎已撤消。接下来(仍然检查feature):

feature

(使用 - 或原始还原提交的其他名称替换git revert W 。例如,在上图中你可以说

W

因为git revert master^ 解析为提交master^。这会给你

W

其中x -- O -- x -- x -- M -- W -- x <--(master) \ / \ A --- B -- C ----------- M2 -- ~W <--(feature) 重做~W撤消的更改。

答案 2 :(得分:0)

因此,在确定使用 git log 确切发生了什么后,我从功能分支创建了一个新分支:

(feature)$ git checkout -b feature-v2
(feature-v2)$ git merge master

然后我通过替换revert commit来恢复恢复(git revert <SHA>):

(feature-v2)$ git revert d992f10ab1106f774e10766be8735a66aeb9eadc

修复了一些合并冲突,然后推送了提交 并确保没有人再次使用旧的功能分支,而是使用 feature-v2