繁体   English   中英

git rebase 交互:将提交合并在一起

[英]git rebase interactive: squash merge commits together

我想有一个简单的解决方案来在交互式 rebase 期间将两个合并提交压缩在一起。

我的存储库看起来像:

   X --- Y --------- M1 -------- M2 (my-feature)
  /                 /           /
 /                 /           /
a --- b --- c --- d --- e --- f (stable)

也就是说,我有一个my-feature分支,最近被合并了两次,中间没有真正的提交。 我不只是想 rebase my-feature分支,因为它是它自己的已发布分支,我只想将最后两个合并提交合并为一个(尚未发布这些提交)

   X --- Y ---- M (my-feature)
  /            /
 /            /
a --- ... -- f (stable)

我试过:

git rebase -p -i M1^

但我得到了:

Refusing to squash a merge: M2

我最后做的是:

git checkout my-feature
git reset --soft HEAD^  # remove the last commit (M2) but keep the changes in the index
git commit -m toto      # redo the commit M2, this time it is not a merge commit
git rebase -p -i M1^    # do the rebase and squash the last commit
git diff M2 HEAD        # test the commits are the same

现在,新的合并提交不再被视为合并提交(它只保留了第一个父项)。 所以:

git reset --soft HEAD^               # get ready to modify the commit
git stash                            # put away the index
git merge -s ours --no-commit stable # regenerate merge information (the second parent)
git stash apply                      # get the index back with the real merge in it
git commit -a                        # commit your merge
git diff M2 HEAD                     # test that you have the same commit again

但是如果我有很多提交,这会变得复杂,你有更好的解决方案吗? 谢谢。

米尔德里德

这是一个古老的话题,但我只是在寻找类似的信息时遇到了它。

Subtree octopus merge中描述的技巧类似的技巧是解决此类问题的一个非常好的解决方案:

git checkout my-feature
git reset --soft Y
git rev-parse f > .git/MERGE_HEAD
git commit

这将使得索引存在于我的特征的顶端,并使用它来创建一个新的Y提交,其中'f'作为第二个父级。 结果就像你从未执行过M1一样,但直接执行M2。

如果您尚未发布最后两个合并提交,则可以执行重置和简单合并。

git reset --hard Y
git merge stable

我来到这个主题想要压缩单个合并提交; 所以我的答案对原始问题没那么有用。

               X
                \   
                 \  
a --- b --- c --- M1 (subtree merge)

我想要的是重新定义M1合并并将所有内容压缩为b之上的单个提交。

a --- b --- S (include the changes from c, X and M1)

我尝试了各种不同的组合,但这是有效的:

git checkout -b rebase b (checkout a working branch at point b)
git merge --squash M1

这会将更改应用到可以提交git commit的索引中

使用原始合并提交的树对象将确保内容保持不变。 commit-tree 可用于具有所需父项和相同内容的新提交。 但是,要使 fmt-merge-msg 生成正常的合并消息,您需要先软重置回 Y。以下是所有内容与通用配方打包在一起:

parent2=$(git rev-parse f)
parent1=Y
merge_branch=stable
tree=$(git rev-parse HEAD^{tree})
git reset --soft $parent1
commit=$(echo $parent$'\t\t'"branch '$merge_branch'" | git fmt-merge-msg | git commit-tree -p $parent1 -p $parent2 -F - $tree
git reset --hard $commit

在我看来,最好的方法是将自己置于合并提交之上并撤消最高提交并修改对先前合并提交的更改。

您将使用以下命令撤消 git-commit:

    git reset HEAD~1

或者

    git reset HEAD^

然后使用:

    git add . && git commit --amend

然后检查结果:

    git log

您应该看到第一个合并提交现在包含两个更改。

此方法可用于所有类型的提交的任何此类需求,或者当

 git rebase -i HEAD~10

... 不能使用。

使用最近的git版本,所提到的方法都不适用于我。 在我的情况下,以下做了诀窍:

git reset --soft Y
git reset --hard $(git commit-tree $(git write-tree) -p HEAD -p stable < commit_msg)

但是,您必须首先将提交消息写入文件commit_msg。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM