2014-01-14 40 views
13

我们在团队中遇到了一个小问题。一位开发者不得不在我们的开发分支中包含一些变化。在这之前,他不小心合并了一个功能分支(当时不应该合并),并继续处理这些更改,在合并之后生成几个提交。删除合并提交,保持当前更改

现在我们想保留这些更改,但在合并完成之前将它们应用于提交。为了保持清晰:

A (+b, +a) 
| 
B (+a) 
| 
C (merge commit) 
|\ 
D \ 
| E (feature branch) 
|/
|/ 
F 

我们希望有自己的变化什么(+ A,+ B)应用在提交d。相当于:

C (+a,+b) 
| 
D 
| E (feature branch) 
|/
|/ 
F 

我们如何提交一个更改来解除先前的合并保留本地更改?

回答

13

这是git rebase -i的工作。兼营:

git rebase -i F 

您将与提交的清单中${EDITOR}呈现,就像这样:

pick 334ad92 D 
pick fb54c42 E 
pick 6901e51 B 
pick 6c61a52 A 

# Rebase eea2847..6c61a52 onto eea2847 
# 
# (more instructions here) 

删除pick fb54c42 E行删除提交。 (另外,如果要将AB合并为一个提交,则可以将pick命令更改为squash-squash 6c61a52 A)。保存并关闭该文件,您的分支机构将处于您希望的状态。

请注意,这将改变历史。这意味着如果您已经将分支推到了任何地方,您就需要执行git push -f,并且会与在此分支上合作的其他人混淆。如果这是一个问题,你可以git revert这次合并提交,而不是:

git revert -m 1 C 

-m 1参数告诉g​​it的恢复对抗的承诺的第一个父,这是被合并到边(D,你的图中) 。

+1

删除选择提交'E'会使它所代表的变化从历史中消失,这不是OP想要的。 – kostix

+0

感谢您的提示! @kostix谢谢指出。虽然我明白阿什想说什么。 – khose

+1

@kostix'E'仍然可以从功能分支到达,尽管(假设它没有被删除)。 –

2

使用git revert C来恢复C合并提交(您可能必须通过-m 1以便Git知道合并的哪一侧保留)。有关详细信息,请参阅How to revert a faulty merge,并详细说明如果继续使用功能部件并在稍后决定再次合并时发生的情况。

回复的方法并不完全给你你要求的;合并带来的承诺仍然是该项目历史的一部分,但其变化将不复存在。完全摆脱提交和合并需要进行重新分配(并在Ash Wilson的回复中进行了描述),这需要仔细考虑,通常不值得付出努力,除非在提交时存在法律限制或技术问题(如巨大的二进制文件)通过合并提交到达。

+0

如果合并是必要的,该怎么办?如果我们恢复合并提交,它会好吗?它不会删除所有更改吗? – Swaps

+0

旧的提交将保留在分支的历史中,但这些提交引入的更改将会消失。 –

5

我不明白的时间表在你的例子什么方向(其提交由之前这)所以我会从广义上解释:

  1. 叉一个新的分支离预合并提交,并检查出来。
  2. git cherry-pick AB那里引入deveoper在合并提交中所做的更改。
  3. 樱桃挑选合并提交后提交的任何提交。

现在你的新分支包含它应该看的历史,所以你现在可能将git reset --hard你的原始分支转移到这个状态。请注意,强制将其推送到共享存储库并由其他开发人员提取它将对他们产生明显影响:每个人都必须根据该分支的旧状态将他们所做的任何工作都设置为新状态。

您可能还想从“固定”分支“强制”关闭功能分支。正如我所说的,我没有看到它是否在之后的违规犯罪之前被分开。如果之前完成,则不需要修复功能分支。

+0

BTW @kostix真的很不错的解决方案,优雅。我昨天忘了告诉你这个:) – khose

0

如果您拥有本地存储库而不是远程存储库,那将非常简单。

当地

  • 功能分支 - 破碎的/不正确的更新提交*
  • 主 - 合并

远程

  • 功能分支 - 更新
  • 主 - 未合并

如果是这种情况,您只需删除本地功能分支和主控,然后从远程存储库中获取/结帐。

希望它仍然有帮助。 :)