重新合并以更改合并提交的父级 [英] Rebasing to change parent of a merge commit

查看:207
本文介绍了重新合并以更改合并提交的父级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有下面的历史,其中第一行是主分支,第二行是一个特征分支,它在一点上与主合并, D 只是恢复 C (这意味着工作目录在 B D中相同)。

  A --- B --- C --- D主人
\\
E --- F --- G功能

我想添加 C 及其在 F 中的合并之前的历史 D 到历史记录中,如下所示:

  A --- B --- C --- D主人
\\
E ----------- F' - G'功能

I don'我想要改变 E (这实际上是一系列长时间的提交)。

git rebase --onto DB (如建议此处)导致合并冲突(有或没有 - preserve-merges )。



有没有办法实现我想要的?

解决方案

大多数方法都会有点痛苦。使用 git filter-branch 有一个中等无痛苦的版本,除了filter-branch本身很痛苦。 :-)(你可以过滤提交 F G 并编写一个提交过滤器,用于替换新父项你需要 F',并让filter-branch操作替换 G 。)



我认为不使用低级命令的最简单的方法就是进行新的合并,然后将 G 转换为新合并。新合并可能会有冲突,但我们并不在意,我们只想采用旧合并的树,我们可以这样做:

  $ git checkout< sha1> #在这里使用D或E的sha-1。 
#请注意:无论您使用何种方式,
#都是我们新的
#merge的第一个父级;基于此选择。
$ git merge --no-commit< sha1> #在这里使用剩余的sha-1
[忽略结果内容]
$ git rm -rf。 #注意:假设你在工作树顶部目录
$ git checkout< sha1-of-F> - 。
$ git commit#创建合并提交F'

第一个 checkout 让你在一个SHA-1的分离HEAD上, merge --no-commit 启动与另一个SHA-1的合并过程, git rm -rf。会抛出合并树和任何冲突,并且 git checkout< id> - 。填充上一次合并的索引和工作树。最后一个 git commit 创建合并 F'与merge F ,但与父母不同。

此时(仍然使用分离的HEAD),您可以重新绑定(或选择)提交 G (或许多提交 G ),然后强制您的分支指向新图形的顶端。我建议使用 git rebase ... --onto HEAD 但我没有用分离的HEAD测试过,至少有一种方法可能会出错(解决 HEAD 给一个ID太晚了)。



低级 git commit-tree 命令实际上可能更简单。 Andrew C在评论中写了正确的命令,尽管你必须用 git update-ref 来说明分支名称。



使用更熟悉的命令的好处在于它们更熟悉。


Suppose I've got the following history, where the top line is the master branch, the lower one is a feature branch that's merged with master at one point, and D just reverts C (which means that the working directory is the same in B and D).

A---B---C---D           master
 \   \
  E---F---G             feature

I want to add C and its reversion D to the history before the merge in F, like this:

A---B---C---D           master
 \           \
  E-----------F'--G'    feature

I don't want to change E (which is actually a long series of commits).

git rebase --onto D B (as suggested here) results in merge conflicts (with or without --preserve-merges).

Is there a way to accomplish what I want?

解决方案

Most methods will be somewhat painful. There's a moderately painless version using git filter-branch, except that filter-branch itself is painful. :-) (You'd filter commits F and G and write a commit-filter that substitutes in the new parents you want for F', and let the filter-branch operation replace the parentage for G.)

I think the simplest method that does not resort to low level commands is just to make a new merge, then rebase G onto the new merge. The new merge may have conflicts but we don't care, we just want to take the old merge's tree, which we can do like this:

$ git checkout <sha1>  # Use D or E's sha-1 here.
                       # Note: whichever you use will
                       # be the first parent of our new
                       # merge; choose based on that.
$ git merge --no-commit <sha1>  # use the remaining sha-1 here
[ignore resulting stuff]
$ git rm -rf .         # Note: assumes you're in top dir of work tree
$ git checkout <sha1-of-F> -- .
$ git commit           # Create merge commit F'

The first checkout gets you on a detached HEAD with one SHA-1, the merge --no-commit starts the merge process with the other SHA-1, the git rm -rf . throws away the merged tree and any conflicts, and the git checkout <id> -- . fills in the index and work-tree from the previous merge. The final git commit creates merge F' with the same tree as merge F, but with different parents.

At this point (still with a detached HEAD) you can rebase (or cherry-pick) commit G (or many commits G), then force your branch to point to the tip of the new graph. I'd suggest using git rebase ... --onto HEAD but I have not tested this with a detached HEAD and there's at least one way it might go wrong (resolving HEAD to an ID too late).

The low level git commit-tree command may actually be even simpler. Andrew C wrote the correct command in a comment, although you have to spell out the branch name with git update-ref. [Edit: maybe not quite correct, the two parents you want are D and E, not D and B. Again, put the one you want as first-parent first.]

The advantage (?) of using the more familiar commands is that they're, well, more familiar.

这篇关于重新合并以更改合并提交的父级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆