将两个分支之间的差异合并到第三个分支

7
假设我有两个分支,一个是master,另一个是new_feature
我原本应该在一个特定的功能上工作,我认为这个功能将成为new_feature的一部分,所以我从new_feature分支中检出了specific_feature分支,如下所示。
git checkout -b specific_feature

现在我在specific_feature分支上进行了很多开发,几次合并upstream/new_feature以获取远程更改。
现在,我知道我的specific_feature应该是从master而不是new_feature分支分支出来的。(new_feature分支还没有准备好被推送)
有没有办法我可以取得specific_feature分支和new_feature分支之间的差异,并将这些更改应用于新分支,比如说specific_feature_master(从master分支创建)?

1
http://stackoverflow.com/a/29136666/1190388 - hjpotter92
2个回答

7

这看起来是需要使用git rebase --onto命令:

git rebase --onto master new_feature specific_feature

那将仅获取从new_featurespecific_feature HEAD之后的提交,并将它们回放到master上。请注意,您随后需要强制推送specific_feature到上游(如果您之前已经推送了它):git push --force specific_feature。如果其他人已经拉取该分支并正在处理它,则可能会出现问题。
davidriod正确指出:

我认为这不会像OP一样工作,因为upstream/new_feature分支已经合并了多次到specific_feature分支。

如果new_feature从未更新过(仅获取,从未拉取),那么它可能仍然有效。如果new_feature被更新(拉取)并合并到specific_feature中,则rebase --onto将仅播放自最后一次合并以来的最后几个提交:在这里,只有z'提交将被回放,而不是第一个z
x--x--x
       \
        y--y--Y--y--y (new_feature)
            \  \
             z--M--z'--z' (specific_feature)

不要挑拣,我会这样做:

  • master中创建specific_feature分支(并将specific_feature分支标记为tmp
  • Y(最后一个合并到specifc_featurenew_feature提交)合并到新的specific_feature分支中

也就是说:

git checkout -b tmp specific_feature
git checkout -B specific_feature master
git merge $(git merge-base tmp new_feature) # that merges Y

        ----------M (specific_feature)
       /         /
x--x--x         /
       \       /
        y--y--Y--y--y (new_feature)
            \  \
             z--M--z'--z' (tmp)

那么 rebase --onto 就可以使用同一个共同祖先 Y 作为正确的基础:

git rebase --onto specific_feature $(git merge-base tmp new_feature) tmp
git branch -D tmp

        ----------M--z''--z'' (specific_feature)
       /         /
x--x--x         /
       \       /
        y--y--Y--y--y (new_feature)

我认为这不会起作用,因为OP已经多次将上游/新功能分支合并到特定功能分支中。 - davidriod
@davidriod 好的,我已经编辑了问题,提出了一种替代的基于合并的选项(而不是 cherry-pick,因为它容易导致提交重复(https://dev59.com/9HE85IYBdhLWcg3wwWQb#2628915))。 - VonC
1
@VonC 我可能理解有误,但基本上这是一个项目中可能发生的特性重新安排,新特性的任何代码都不应该合并到主分支中。关于提交重复,如果特定特性将被删除,则这不是真正的问题。基本上,我认为 OP 只是想独立地重构 specific_feature,而不是从 new_feature 分支开始。 - davidriod

2
您可以使用命令 git cherry 来检索在 specific_feature 分支上完成的提交,但未出现在 origin/new_feature 分支上。
git cherry origin/new_feature specific_feature

您可以从master创建一个新的分支,并cherry-pick所有这些提交。 但是,如果您在specific_feature中进行开发的依赖项与origin/new_feature之间存在依赖关系,那么没有任何源代码管理工具会为您解决这个问题。
git checkout -b specific_feature_master master
git cherry origin/new_feature specific_feature | egrep '^+' | awk '{print $2} | xargs git cherry-pick

类似这样的东西应该是解决你问题的一个起点。


1
git cherry origin/new_feature specific_feature | egrep '^\+' | awk '{print $2}' | xargs git cherry-pick 的最后一行进行了微小的修改。 - Edwin Hoogerbeets

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接