我们的团队遇到了一个小问题。一个开发者必须在我们的开发分支中包含一些变化。在这之前,他意外地合并了一个功能分支(当时不应该合并)并继续处理这些更改,在合并后生成几个提交。
现在我们要保留这些更改,但在合并完成之前将它们应用于提交。为了清楚起见:
A (+b, +a)
|
B (+a)
|
C (merge commit)
|\
D \
| E (feature branch)
| /
|/
F
我们希望将他的更改(+ a,+ b)应用于提交 D 。相当于:
C (+a,+b)
|
D
| E (feature branch)
| /
|/
F
我们如何提交更改以解除保留本地更改的先前合并?
答案 0 :(得分:14)
这是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
行以删除该提交。 (另外,如果您希望将A
和B
合并为一个提交,则可以将pick
命令更改为squash
- squash 6c61a52 A
)。保存并关闭文件,您的分支将处于您希望的状态。
请注意这将更改历史记录。这意味着如果你已经将分支推到了任何地方,你将需要做一个git push -f
,并且它会混淆那些在这个分支上合作的人。如果这是一个问题,您可以git revert
合并提交:
git revert -m 1 C
-m 1
参数告诉git恢复提交的第一个父级,这是在图中合并到(D
)的一侧。
答案 1 :(得分:5)
我无法理解时间轴在您的示例中有哪些方向(在此之前提交了哪些提交),因此我将从广义上解释:
git cherry-pick A
和B
用于引入开发者在合并提交中所做的更改。到目前为止,您的新分支包含了它应该查看的历史记录,因此您现在可以git reset --hard
将原始分支git rebase
置于此状态。请注意,强制将其推送到共享存储库并由其他开发人员获取它将对他们产生明显的影响:每个人都必须{{1}}根据该分支的旧状态到其新状态所做的任何工作
您可能还想从“固定”分支“重新创建”功能分支。正如我所说,我没有看到它是否在违规提交之前分叉。如果以前完成,则无需修复功能分支。
答案 2 :(得分:2)
使用git revert C
恢复C合并提交(您可能必须传递-m 1
,以便Git知道合并的哪一侧要保留)。有关详细信息,请参阅How to revert a faulty merge,详细说明如果继续处理功能分支以及稍后决定再次合并将会发生什么。
恢复方法并不能完全满足您的要求;合并带来的提交仍然是项目历史的一部分,但他们的改变将会消失。完全摆脱提交和合并将需要一个rebase(并在Ash Wilson的回复中描述),这需要仔细考虑并且通常不值得努力,除非有提交的法律限制或技术问题(如巨大的二进制文件)通过合并提交到达。
答案 3 :(得分:0)
如果你有一个本地存储库而不是远程存储库,那就很容易了。
本地
远程
如果是这种情况,您只需要删除本地feature-branch和master,然后从远程存储库中获取/ checkout。
希望它仍然有帮助。 :)