我可以将推送提交从一个分支移动到另一个现有分支吗?

Glu*_*ear 11 git git-branch

我有 3 个分支:develop,feature-1feature-2. 我在工作feature-1,然后切换到工作feature-2。然后我完成了工作feature-2,提交并推送到 repo,然后为该功能创建了一个合并请求。然后我看到其中feature-2包含一些应该在feature-1. 我可以将它们从本地移动feature-2feature-1本地,然后在回购中反映相同的移动吗?

bei*_*ish 15

git cherry-pick <commit-id> 是你亲爱的朋友吗?

  1. 继续功能 2 分支
  2. 复制commit-id(s)您想从移动feature-2feature-1
  3. 切换到功能 1 分支
  4. 现在挑选你在上面第 2 步中复制的所有提交。

    git cherry-pick <commit-id>

    如果您有多个提交要移动,feature-1则将所有提交 ID 按提交日期/时间顺序排列。

    例如:

    git cherry-pick <commit-id-1> <commit-id-2> . . <commit-id-n>

  • 从技术上讲,您不会*移动*提交,而是创建一个具有相同内容的新提交,并且 git 在合并时会记住此副本。 (2认同)

Mar*_*ger 9

你的问题说,在问题提交属于feature-1,而不是在feature-2分支。接受的答案并没有做到这一点。

cherry-pick是在一个分支上创建新提交以复制另一个分支上提交所做的更改的好方法;但它不会改变另一个分支。

因此,例如,如果您从

x <--(master)
|\
| A1 -- A2 <--(feature_1)
 \
  B1 -- A3 -- B2 <--(feature_2)
Run Code Online (Sandbox Code Playgroud)

A3用于哪里feature_1,按照cherry-pick程序后,您将拥有

x <--(master)
|\
| A1 -- A2 -- A3' <--(feature_1)
 \
  B1 -- A3 -- B2 <--(feature_2)
Run Code Online (Sandbox Code Playgroud)

所以feature_1可能看起来你现在想要它,但feature_2仍然有一些它不应该有的变化。当您将两个功能合并到master. (我的意思是,可能存在没有多大意义的合并冲突。 git确实尝试在这里提供帮助,但它不可能是完美的。)

在您的问题中,您注意到提交已经被推送,并且作为对cherry-pick答案的回应,您询问更改是否push干净;所以我假设您已经遇到(至少部分)在您推送的分支上重写历史记录的问题。

虽然结果确实cherry-pickpush干净利落,但那是因为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
Run Code Online (Sandbox Code Playgroud)

给你

x <--(master)
|\
| A1 -- A2 -- A3' <--(feature_1)
 \
  B1 -- A3 -- B2 -- !A3 <--(feature_2)
Run Code Online (Sandbox Code Playgroud)

这仍然会很push干净(因为没有从任何分支的历史记录中删除任何提交)并且两个分支现在都会有正确的更改。从好的方面来说,这使得您不太可能遇到任何合并问题;不利的一面是,某些rebase操作现在可能会出现问题。您可能会采取一些措施来缓解这种情况,但是如果您担心只进行push干净利落的更改,那么rebase无论如何您都不会这样做。

如果您想要“移动”许多提交,那么您可能需要将 替换为cherry-pick交互式rebase,如下所示:

git checkout feature-2
git branch temp
git rebase -i feature-1 temp
Run Code Online (Sandbox Code Playgroud)

将打开一个编辑器,显示 .todo 的“待办事项”列表rebase。列表中的每个条目都是关于如何处理提交的说明。删除要“留下”的提交行。(您还可以对如何在 上表示提交进行其他调整feature-1;但这是一个很长的兔子洞,因为到目前为止您所问的只是如何“移动”提交,因此这些步骤将使它们保持“原样” ”。)

当您保存并退出编辑器时,rebase将开始重写所有选定的提交。完成更新到feature-1by

git checkout feature-1
git merge temp
git branch -d temp
Run Code Online (Sandbox Code Playgroud)

你仍然需要去feature-2恢复不应该在那里的提交;您可能希望在带有-n标志的单个命令中执行此操作,以便您可以只创建一个还原提交。(这将有降低风险的副作用,我上面提到,某些rebase操作演戏了,你做之后revert;但同样,我希望你不会做这些类型的rebase都会给出这个问题隐含的约束。)

现在有些人不喜欢使用revert这种东西,因为历史显示了发生的事情——包括进行更改和稍后删除更改,这可能看起来很烦人,因为不应该进行更改。

避免这种情况的唯一方法是“重写历史” feature-2,无论你怎么做,都不会push干净。您可以其转至push,但这样做您将为拥有 副本的所有其他开发人员创建工作feature-2- 如果他们做错了事,您的工作将被撤销。所以如果你想重写历史,你必须与使用 repo 的其他人协调。有关git rebase更多信息,请参阅“从上游变基恢复”下的文档。