我有3个分支:develop
,feature-1
和feature-2
。我正在feature-1
工作,然后转而使用feature-2
。然后我完成了feature-2
的工作,提交并推送到了repo,然后为该功能创建了合并请求。然后我看到feature-2
包含一些应该在feature-1
中的提交。我可以在本地将它们从feature-2
移动到feature-1
,然后在回购中反映相同的动作吗?
答案 0 :(得分:2)
您的问题是有问题的提交属于feature-1
中的,而不属于feature-2
分支。接受的答案没有达到这个目的。
cherry-pick
是一种在一个分支上创建新提交的好方法,它可以复制另一个分支上的提交所做的更改;但它不会改变另一个分支。
例如,如果您是从
开始的话x <--(master)
|\
| A1 -- A2 <--(feature_1)
\
B1 -- A3 -- B2 <--(feature_2)
其中A3
适用于feature_1
,遵循cherry-pick
程序后您将拥有
x <--(master)
|\
| A1 -- A2 -- A3' <--(feature_1)
\
B1 -- A3 -- B2 <--(feature_2)
所以feature_1
现在可能看起来像你想要的那样,但是feature_2
仍然有一些它可能不应该有的变化。将这两个要素合并到master
时,这可能会导致一些问题。 (我的意思是,可能存在一些没有多大意义的合并冲突。git
确实试图在这里提供帮助,但它并不完美。)
在您的问题中,您注意到提交已经被推送,并且在回答cherry-pick
答案时,您会询问更改是否push
干净利落;所以我假设你遇到了(至少有一些)在你推动的分支上重写历史的问题。
虽然cherry-pick
的结果确实会push
干净利落,但这是因为cherry-pick
没有进行您要求的所有更改(如上所述)。这是feature-2
的修复,确实导致了push
的问题。
一种解决方案是使用cherry-pick
来修复feature-1
,然后使用revert
修复feature-2
。在我们的示例中,使用feature-2~1
作为标识要“移动”的提交的表达式(通常可以使用提交ID或适合您实际情况的表达式):
git checkout feature-1
git cherry-pick feature-2~1
git checkout feautre-2
git revert feature-2~1
给你
x <--(master)
|\
| A1 -- A2 -- A3' <--(feature_1)
\
B1 -- A3 -- B2 -- !A3 <--(feature_2)
这仍然会push
干净利落(因为没有从任何分支的历史中删除任何提交),现在两个分支都会有正确的更改。从好的方面来说,这使得您不太可能遇到任何合并问题;在不利方面,某些rebase
操作现在可能会出现问题。您可以采取一些措施来缓解这种情况,但如果您担心只是干净地进行push
更改,那么无论如何您都不会采用rebase
。
如果您想要“移动”多次提交,那么您可能希望将cherry-pick
替换为交互式rebase
,如下所示:
git checkout feature-2
git branch temp
git rebase -i feature-1 temp
将打开一个编辑器,显示rebase
的“待办事项”列表。列表中的每个条目都是如何处理提交的说明。删除要“留下”的提交行。 (你可以对如何在feature-1
上表示提交进行其他调整;但这是一个很长的兔子洞,因为到目前为止你所要求的是如何“移动”提交,所以这些步骤将会保持他们“按原样”。)
当您保存并退出编辑器时,rebase
将开始,重写所有选定的提交。通过
feature-1
的更新
git checkout feature-1
git merge temp
git branch -d temp
您仍然需要转到feature-2
以恢复不应该存在的提交;您可能希望在具有-n
标志的单个命令中执行此操作,以便您只能创建一个还原提交。 (这会产生副作用,即降低我上面提到的风险,某些rebase
操作在执行revert
之后起作用;但同样,我希望你不会做那些类型的rebase
无论如何,考虑到这个问题所暗示的限制。)
现在有些人不喜欢使用revert
来做这种事情,因为历史记录显示发生了什么 - 包括进行更改然后删除更改,这可能看起来很烦人,因为改变应该永远不会制成。
避免这种情况的唯一方法是“重写feature-2
的历史记录”,无论你怎么做,都不会push
干净利落。你可以将发送到push
,但这样你就可以为拥有feature-2
副本的所有其他开发人员创建工作 - 如果他们做错了什么的话,它会撤消你的工作。因此,如果要进行历史记录重写,则必须与使用回购的其他人协调。有关详细信息,请参阅“从上游rebase恢复”下的git rebase
文档。
答案 1 :(得分:0)
git cherry-pick <commit-id>
是你的朋友。
commit-id(s)
您希望从feature-2
移至feature-1
现在,请选择您在上面的步骤2中复制的所有提交。
git cherry-pick <commit-id>
如果要将多个提交移动到feature-1
,则将所有提交ID按其提交日期/时间顺序排列。
例如:
git cherry-pick <commit-id-1> <commit-id-2> . . <commit-id-n>