合并提交不会出现在 git rebase --interactive 中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24786404/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 10:13:17  来源:igfitidea点击:

Merge commits don't appear in git rebase --interactive

gitgit-interactive-rebase

提问by NWard

git logreveals the following:

git log揭示了以下内容:

commit 1abcd[...]
Author: [...]
Date: [...]

    [Useful commit]

commit 2abcd[...]
Author: [...]
Date: [...]

    Merge branch [...] of [etc. etc.]

commit 3abcd[...]
Author: [...]
Date: [...]

    [Useful commit]

That merge commit is useless to me - it doesn't represent a meaningful state of the branch and was generated from a remote pull, so I have the real commits of the remote history - no need for a commit to mark the fact that I pulled. I would like to squash this merge commit. My usual technique for doing a squash is:

那个合并提交对我来说没用 - 它不代表分支的有意义的状态并且是从远程拉取生成的,所以我有远程历史的真实提交 - 不需要提交来标记我拉取的事实. 我想压缩这个合并提交。我做壁球的常用技巧是:

git rebase --interactive HEAD~2(or however far back I need to go)

git rebase --interactive HEAD~2(或者我需要走多远)

And then I would squash it into a neighboring commit. I do this some times if for example I make a commit, realize I missed a tiny important detail (single file, or hadn't changed a line in one of the files), and do another commit that's basically just a quick oops. That way when I push my changes back to the remote, everything is nice and clean and tells a cohesive narrative.

然后我会将它压缩到相邻的提交中。有时我会这样做,例如,如果我进行了一次提交,意识到我错过了一个很小的重要细节(单个文件,或者没有更改其中一个文件中的一行),然后再进行一次提交,这基本上只是一个快速的 oops。这样,当我将更改推回遥控器时,一切都变得美好而干净,并讲述了一个有凝聚力的叙述。

However, in this case, when I run the git rebase ...command, commit 2abcddoesn't appear! It seems to skip right over 2abcdand instead displays 1abcdand 3abcd. Is there something special about a merge commit that prevents it from being appearing in git rebase --interactive? What other technique could I use to squash that merge commit?

但是,在这种情况下,当我运行git rebase ...命令时,2abcd不会出现提交!它似乎直接跳过2abcd,而是显示1abcd3abcd。合并提交有什么特别之处可以防止它出现在 中git rebase --interactive吗?我可以使用什么其他技术来压缩合并提交?

UPDATEper @Cupcake's request:

UPDATE每@蛋糕的要求:

The output of git log --graph --oneline --decoratelooks like this:

的输出git log --graph --oneline --decorate如下所示:

* 1abcd (useful commit)
* 2abcd (merge)
|  \ <-- from remote
|   * 3abcd (useful commit)
|   |

Helpful?

有用吗?

回答by

Rebase doesn't normally preserve merge commits without --preserve-merges

Rebase 通常不会在没有的情况下保留合并提交 --preserve-merges

Ok, so I'm not exactly sure what would happen if you tried to squash a merge commit using an interactive rebase with --preserve-merges...but this is how I would remove the merge commit in your case and make your history linear:

好的,所以我不确定如果您尝试使用交互式 rebase 压缩合并提交会发生什么--preserve-merges......但这就是我将在您的情况下删除合并提交并使您的历史线性化的方法:

  1. Rebase everything before the merge commit on top of the remote branch.

  2. Cherry-pick or rebase everything after the merge commit on top of the previously rebased commits.

  1. 在远程分支之上的合并提交之前重新设置所有内容。

  2. 在合并提交之后,在先前重新调整的提交之上挑选或重新调整所有内容。

If you only have 1 commit after the merge commit

如果在合并提交后只有 1 次提交

So in terms of commands, that would look something like this:

所以就命令而言,这看起来像这样:

# Reset to commit before merge commit
git reset --hard <merge>^

# Rebase onto the remote branch
git rebase <remote>/<branch>

# Cherry-pick the last commit
git cherry-pick 1abcd 

If you have more than 1 commit after the merge commit

如果您在合并提交后有 1 个以上的提交

# Leave a temporary branch at your current commit
git branch temp

# Reset to commit before merge commit
git reset --hard <merge>^

# Rebase onto the remote branch
git rebase <remote>/<branch>

# Cherry-pick the last commits using a commit range.
# The start of the range is exclusive (not included)
git cherry-pick <merge>..temp

# Alternatively to the cherry-pick above, you can instead rebase everything
# from the merge commit to the tip of the temp branch onto the other
# newly rebased commits.
#
# You can also use --preserve-merges to preserve merge commits following
# the first merge commit that you want to get rid of...but if there were
# any conflicts in those merge commits, you'll need to re-resolve them again.
git rebase --preserve-merges --onto <currentBranch> <merge> temp

# These next steps are only necessary if you did the rebase above,
# instead of using the cherry-pick range.
#
# Fast-forward your previous branch and delete temp
git checkout <previousBranch>
git merge temp
git branch -d temp

Documentation

文档