git rebase Interactive:将提交压缩在一起

发布于 2024-08-11 12:06:06 字数 1558 浏览 12 评论 0原文

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

我的存储库看起来像:

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

也就是说,我有一个 my-feature 分支,最近已合并两次,其间没有真正的提交。我不仅仅是想对 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

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

米尔德里德

I wanted to have a simple solution to squash two merge commits together during an interactive rebase.

My repository looks like:

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

That is, I have a my-feature branch that has been merged twice recently, with no real commits in between. I don't just want to rebase the my-feature branch since it is a published branch of its own, I just want to squash together the last two merge commits into one (haven't published those commits yet)

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

I tried:

git rebase -p -i M1^

But I got:

Refusing to squash a merge: M2

What I finally did is:

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

Now, the new merge commit is not considered a merge commit anymore (it only kept the first parent). So:

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

But this can get complicated if I have many commits, do you have a better solution ?
Thanks.

Mildred

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

网名女生简单气质 2024-08-18 12:06:06

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

类似于子树章鱼合并中描述的技巧对于此类问题来说,这是一个非常好的解决方案:

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

它将采用 my-feature 顶端存在的索引,并使用它从 Y 创建一个新的提交,并以“f”作为第二个父级。结果就像您从未执行过 M1,而是直接执行 M2 一样。

This is an old topic, but I just ran across it while looking for similar information.

A trick similar to the one described in Subtree octopus merge is a really good solution to this type of problem:

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

That will take the index as it exists at the tip of my-feature, and use it to create a new commit off of Y, with 'f' as a second parent. The result is the same as if you'd never performed M1, but gone straight to performing M2.

雨的味道风的声音 2024-08-18 12:06:06

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

git reset --hard Y
git merge stable

if you haven't published the last two merge commits, you could do a reset and a simple merge.

git reset --hard Y
git merge stable
梦里梦着梦中梦 2024-08-18 12:06:06

我来到这个主题是想压缩单个合并提交;所以我的回答对原来的问题没有多大用处。

               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 提交

I came to this topic wanting to squash a single merge commit; so my answer is not that useful to the original question.

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

What I wanted was to rebase the M1 merge and squash everything as a single commit on top of b.

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

I tried all kinds of different combinations but this is what worked:

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

This will apply the changes into the index where they can be committed
git commit

浅黛梨妆こ 2024-08-18 12:06:06

使用原始合并提交的树对象将确保内容保持不变。 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 $parent2

这是一个可以放在 ~/.fmt-merge-msg 中的别名。 gitconfig:

[alias]
    remerge = "!f() { p1=$1; p2=`git rev-parse $2`; t=`git rev-parse HEAD^{tree}`; git reset --soft $p1; git reset --hard `echo $p2

启用:

git remerge <parent1-rev> <parent2-rev> [<parent2-branch>]
\t\t'"branch $merge_branch" | git fmt-merge-msg | git commit-tree -p $parent1 -p $parent2 -F - $tree) git reset --hard $commit

这是一个可以放在 ~/.fmt-merge-msg 中的别名。 gitconfig:


启用:


\t\t'"branch ${3:-$2}" | git fmt-merge-msg | git commit-tree -p $p1 -p $p2 -F - $t`; }; f"

启用:

\t\t'"branch $merge_branch" | git fmt-merge-msg | git commit-tree -p $parent1 -p $parent2 -F - $tree) git reset --hard $commit

这是一个可以放在 ~/.fmt-merge-msg 中的别名。 gitconfig:

启用:

Using the tree object of the original merge commit will ensure the content is left unchanged. commit-tree can be used to make a new commit with the desired parents and the same content. But, for fmt-merge-msg to produce a normal merge message, you'll need to first soft reset back to Y. Here is everything packaged up with a generic recipe:

parent2=$(git rev-parse f)
parent1=Y
merge_branch=stable
tree=$(git rev-parse HEAD^{tree})
git reset --soft $parent1
commit=$(echo $parent2

Here is an alias that can be put in your ~/.gitconfig:

[alias]
    remerge = "!f() { p1=$1; p2=`git rev-parse $2`; t=`git rev-parse HEAD^{tree}`; git reset --soft $p1; git reset --hard `echo $p2

To enable:

git remerge <parent1-rev> <parent2-rev> [<parent2-branch>]
\t\t'"branch $merge_branch" | git fmt-merge-msg | git commit-tree -p $parent1 -p $parent2 -F - $tree) git reset --hard $commit

Here is an alias that can be put in your ~/.gitconfig:


To enable:


\t\t'"branch ${3:-$2}" | git fmt-merge-msg | git commit-tree -p $p1 -p $p2 -F - $t`; }; f"

To enable:

\t\t'"branch $merge_branch" | git fmt-merge-msg | git commit-tree -p $parent1 -p $parent2 -F - $tree) git reset --hard $commit

Here is an alias that can be put in your ~/.gitconfig:

To enable:

最笨的告白 2024-08-18 12:06:06

对于我最新的 git 版本,上述方法都不起作用。在我的例子中,以下方法达到了目的:

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

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

None of the mentioned methods works for me with a recent git version. In my case the following did the trick:

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

You'll have to write the commit message to the file commit_msg first, though.

走走停停 2024-08-18 12:06:06

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

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

    git reset HEAD~1

    git reset HEAD^

然后使用:

    git add . && git commit --amend

然后使用以下命令检查结果:

    git log

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

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

<前><代码> git rebase -i HEAD~10

...无法使用。

In my opinion, the best method is to place yourself on top of the merge-commits and undo the top commit and amend the changes to the previous merge-commit.

You will undo a git-commit with the following command:

    git reset HEAD~1

or

    git reset HEAD^

Then use:

    git add . && git commit --amend

Then check the results with:

    git log

You should see that the first merge-commit now has both changes included.

This method can be used for any such needs for all type of commits, or when

    git rebase -i HEAD~10

... cannot be used.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文