Git从master到feature分支问题

时间:2017-08-22 19:52:22

标签: git github

我的情况如下:

  1. 我已经从master创建了一个开发分支。在开发分支中重命名/移动文件(将文件a.jsp移动到b.jsp)并将更改推送到远程源/开发分支。
  2. 但是主人仍然有a.jsp。由于master是公共分支,另一个用户正在进行功能更改,现在将更改提交/合并到master。这意味着a.jsp文件中有变化。
  3. 当我尝试" git rebase master"将更改从主分支拉到我的开发分支。我现在看到文件a.jsp和b.jsp。 BUt我想将master / a.jsp中的新更改提取到开发分支b.jsp。而不是同时拥有这两个文件。
  4. 有人可以指导我如何更好地处理这个问题吗?

1 个答案:

答案 0 :(得分:1)

目前还不清楚为什么rebase不会显示合并冲突(在一方删除a.jsp和另一方修改a.jsp之间)。因为它没有,如果你想让rebase产生所需的结果,你需要做一个交互式的rebase。

在评论中,您询问是否应该避免变基。可能有理由考虑这一点。如果development是所有回购用户共享的长期分支,那么您可能不希望将其变为工作流的常规部分。但是把它放在一边,对于这种特殊的变化组合没有什么可以阻止你使用rebase。我将概述如何进行改造工作,因为这解决了原始问题;你和你的团队必须决定这是否正确。

有可能在早期的rebase尝试之后完成这项工作,但是如果你可以先恢复你在尝试rebase之前所拥有的东西,那么可能更容易跟踪事物的状态并避免错误。你可以通过创建一个新的原始克隆来做到这一点(假设你没有推动第一个rebase的结果)。如果你这样做,有些东西(比如reflogs)会丢失;另一种选择是使用reflog来帮助你恢复当前的克隆。

git reflog development

输出应该显示development指向的每个提交,为每个提交命名development@{1}development@{2}等。您可以在rebase之前识别出一个做一个reset。例如,我假设rebase是导致development ref更改的最新事件,在这种情况下,rebase之前的状态将为development@{!}

git checkout development
git reset --hard development@{1}

接下来,以交互模式重新启动rebase。

git rebase --interactive master development

您将获得一个编辑器,其中包含development分支上的提交列表。它看起来像

pick aaaaaaaa Some changes
pick bbbbbbbb move a.jsp to b.jsp; maybe more changes
pick cccccccc more changes

找到您将a.jsp移至b.jsp(上例中为bbbbbbbb)的提交,并将该行开头的单词pick更改为{{ 1}}。保存并关闭编辑器。此时,rebase处理应该开始。

你接下来做什么取决于git的作用。既然你之前没有发生任何冲突就表示它完成了变基,我认为不会再有冲突;因此,重播edit后,处理将停止。

如果bbbbbbbb仅移动了文件而没有更改,那么您可以简单地

bbbbbbbb

然后继续rebase。请注意,如果mv a.jsp b.jsp git add a.jsp b.jsp git commit --amend 更改aaaaaaaa,那就没问题; git在重播a.jsp时已经合并了这些更改。同样,如果aaaaaaaa更改cccccccc,那么此时并不重要。我们只关心b.jsp除了重命名文件外,还改变了它。如果确实如此,那么您可能需要告诉git组合更改(可能通过执行文件级合并)。

在我看来,这里需要一点额外的谨慎,因为篮板的行为并不像我期望的那样(因为它没有看到bbbbbbbb development的移动{ {1}} a.jspb.jspmaster的更改有冲突。所以我会看看a.jsp并验证git已经对其进行了哪些更改。理想情况下,它已经反映了b.jsp的变化(虽然我不认为它会;如果确实如此,我不会期望master出现。)

如果确实包含a.jsp的更改,那么您很幸运。您所要做的就是删除master

a.jsp

但除此之外,我希望您发现rm a.jsp git add a.jsp git commit --amend 包含a.jsp的更改以及master的所有更改,而aaaaaaaa包含b.jsp的任何更改{1}}和aaaaaaaa。在bbbbbbbb命令中,merge-file将是"当前文件" (有时称为"我们的")和b.jsp将是"其他文件" (有时称为"他们的#34;)。我们需要获取基本文件。

我们重新命名a.jsp,以便我们不会忘记他们的"他们"我们签出基本版本的版本。

a.jsp

mv a.jsp a.jsp.theirs git checkout HEAD^^ -- a.jsp 命令从checkout提交的重写版本(在a.jsp移动到aaaaaaaa之前的最后一次提交中获取a的版本})。这应该包含"我们的"中的所有变化。和"他们的",没有其他变化,所以这是一个很好的合并基础。所以

b

这将执行文件级合并。它可以记录冲突(就像git中的任何常规合并一样),您必须通过编辑git merge-file b.jsp a.jsp a.jsp.theirs 来解决。完成后,您可以删除b.jspa.jsp。然后

a.jsp.theirs

所以基本上所有的道路都会导致这个git add a.jsp b.jsp git commit --amend 命令,一旦完成,你可以重新启动rebase

commit --amend

如果后续提交(git rebase --continue )包含对cccccccc的更改,希望他们只会被合并(但可能会产生冲突) ,需要进一步干预)。