如何使用git rebase来压缩合并周围的提交?

时间:2016-06-23 01:54:49

标签: git git-merge git-rebase

使用git进行合并的最简单方法是什么?

在我的一个分支机构中,我一直在推测着一堆不同的东西,大量的失败和部分失败的尝试。现在我已经开始工作了,我想回过头来尝试使用交互式变基,压制一堆猜测和检查提交。

复杂的是,在这个过程中我合并了另一个分支。我想保持合并分支的原样(不重写任何提交),并将合并提交保持在我的分支中相同的相对位置。 (因为我的分支中的功能依赖于之前/之后。)我尝试了直接git rebase -i,但我合并的分支从我持续的点开始有相当多的提交分歧,并且当它们出现在交互式rebase文件中时,它们使事情变得复杂。

图表可能有所帮助。我现在拥有的:

#-#-#-#-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* My branch
 \                   /      
  #-#-#-#-#-#-#-#-#-#-#-#-# The merged branch

我想要的是什么:

#-#-#-#-----*-------*-*----*------* My branch
 \                   /      
  #-#-#-#-#-#-#-#-#-#-#-#-# The merged branch

("#"我想保持相同的提交,SHA1方式,两个合并提交的文件系统内容应该相同。)

我还没有将我想要的任何提交推送到远程服务器。 (虽然我合并的分支在远程服务器上是。)

3 个答案:

答案 0 :(得分:3)

DavidN's answer是正确的 - 请记住,rebase只是复制提交 - 但执行起来有点棘手。您需要保存两个特定的提交ID,甚至可能使用另一个分支名称。

我实际上会使用新的分支名称和git cherry-pick以及新的git merge来实现此目的。这是方法,使用您的图表,稍微注释,以及一些实际的Git命令。你有:

A-#-#-B-*-*-*-*-*-*-C-M-D-*-*-*-*-*-*-E My branch
 \                   /      
  #-#-#-#-#-#-#-#-#-#-#-#-# The merged branch

你想:

A-#-#-B-----*-------*-m----*------* My branch
 \                   /      
  #-#-#-#-#-#-#-#-#-#-#-#-# The merged branch

您可以从:

开始
git checkout -b rebased B

它会为您提供一个指向commit B的新分支名称。现在你可以:

git cherry-pick -n B..C

(或使用原始ID)复制*之后的所有B次提交,包括C,然后git rebase -i B并压缩一些以获取您的两个{{ 1}}提交。

现在你准备合并;所以*与来自git merge M^2的提交M的第二父母合并。The merged branch。如果失败(或者如果你想修改它,添加--no-commit,现在你就停止它了),你可以通过直接从commit M检查文件来修复合并,假设你想要相同的合并你在那里的决议。

(如果你启用了git rerere,那么大部分时间都会自动发生。)

提交或合并完成后,您将获得新合并提交{ID 1}的ID。

现在,您已准备好挑选提交mD,包括:{/ p>

E

(我们需要git cherry-pick D^..E 来获取D^ - 或者您可以使用提交D的原始SHA-1 ID(原始合并)。然后M重新定义git rebase -i m - 到 - D的新副本,而无需通过新合并E进行备份。

完成所有操作后,您将获得所需的图表。然而,分支的名称是m而不是rebased 1 ,并且您有分支My branch指向提交My branch。所以E然后git checkout My branch将旧名称指向新的branch-tip-commit,之后您可以删除名称git reset --hard rebased

1 显然这不是实际名称,因为在分支名称中有空格是坏的。

答案 1 :(得分:2)

你可以采用手动方法,只需在MyBranch的第一个分支提交到TheMergedBranch之间在MyBranch上进行交互式rebase,以压缩你的东西。然后在TheMergedBranch中合并。然后做一个交互式的rebase - 你的新分支与上游和提交从原始的MyBranch获取那些。

答案 2 :(得分:0)

不要使用rebase,使用移植物。请记住,提交是完全内容的快照,因此您想要的提交与现有提交的内容完全相同,您只想重新连接父级。那是什么样的移植物。

首先,在沙箱回购中执行此操作,以便在不喜欢发生的情况下放弃并擦除它:

git clone -s . "${other=`mktemp -dt`}"
cd "$other"

设置您想要的父母

echo > .git/info/grafts $(git rev-parse M B M^2)
echo >>.git/info/grafts $(git rev-parse E M)

(我认为你在那里有一两个你想要的提交,只需列出你真正想要的父母的提交,而不是你已经获得的那些,git的修订版走路将跟随你的领导)

然后

git filter-branch -- --all

如果你喜欢结果,请将它们推回去。