42

git log揭示以下内容:

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

    [Useful commit]

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

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

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

    [Useful commit]

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

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

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

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

根据@Cupcake的要求更新:

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

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

有帮助吗?

4

2 回答 2

41

Rebase 通常不会保留合并提交--preserve-merges

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

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

  2. 在合并提交之后,在先前重新设置的提交之上进行 Cherry-pick 或重新设置所有内容。

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

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

# 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 

如果您在合并提交后有超过 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

文档

于 2014-07-16T18:01:17.733 回答
9

Git 提供了一种新的使用方式--rebase-merges

在 --rebase-merges 之前,我与我的具体案例有 6 个冲突。

git rebase -i --rebase-merges origin/master

你可能会看到类似的东西:

label onto

reset 4127388 # Formatting
pick 87da5b5 feat: add something
pick 8fcdff4 feat: add ..
merge -C 80784fe onto # Merge remote-tracking branch 'origin/master' into a-branch-name
pick 3d9fec7 add unit tests
于 2021-05-19T10:26:17.157 回答