为什么git log --cherry-pick不能删除等效的提交?

25

我一直在尝试使用

git log --no-merges --cherry-pick --right-only master...my-branch

按照 git-log 文档,生成一个列出“我的分支”中但不在主分支(master)中提交记录的列表。然而,列表中仍有许多等效的提交记录。如果我显示它们及其补丁,则除了提交 ID 之外没有任何区别。

git show 16cbd0e47406a4f7acbd6dc13f02d74d0b6a7621 >patcha
git show c53c7c32dcd84bfa7096a50b27738458e84536d5 >patchb

diff patcha patchb
1c1
< commit 16cbd0e47406a4f7acbd6dc13f02d74d0b6a7621
---
> commit c53c7c32dcd84bfa7096a50b27738458e84536d5

即使git patch-id也显示它们是等价的:

git show c53c7c32dcd84bfa7096a50b27738458e84536d5 | git patch-id
2b5504fb9a8622b4326195d88c7a20f29701e62b c53c7c32dcd84bfa7096a50b27738458e84536d5
git show 16cbd0e47406a4f7acbd6dc13f02d74d0b6a7621 | git patch-id
2b5504fb9a8622b4326195d88c7a20f29701e62b 16cbd0e47406a4f7acbd6dc13f02d74d0b6a7621

如何使用git log --cherry-pick时不将这些内容视为重复?


这个问题应该在 Git 2.31(2021年第一季度)中得到解决:https://stackoverflow.com/a/65946225/6309 - VonC
2个回答

6
自从进行了cherry-pick操作后,您是否已将master合并到了您的分支中?--cherry-pick首先按照提交ID进行匹配,如果失败,则查找patch ID。如果您已经将master合并到了您的分支中,那么您现在的分支上就有了实际的提交以及cherry-pick的版本。所以它会找到提交ID,然后继续报告已经cherry-pick的版本。
我常常想知道git是否应该总是检查两者,但这可能会带来相当大的性能损失。

4
选择性挑选代码(Cherry-picking)将会引入一个新的提交编号,因为父节点或时间已经改变。但是如果master分支合并到了my-branch分支,那么这两个版本现在都存在于该分支上,所以挑选的版本将被报告,因为使用提交编号完全匹配会优先考虑。尝试使用git branch --contains 16cbd0egit branch --contains c53c7c3命令。我敢打赌其中至少一个显示了mastermy-branch两个分支。需要考虑的一件事是,如果你要合并一个分支,最好不要从中进行选择性挑选。不仅因为这个原因,还因为它会使历史记录变得混乱。 - John Szakmeister
2
这仍然困扰着我。我们合并以保持历史记录的一致性,但最终我们确实会进行挑选,因为很难强制执行知道在何处完成工作的纪律。挑选已经成为不可避免的事情。错误首先得到修复,位置通常是事后想到的。如果您有除编写自己的工具查看补丁 ID 之外的其他想法,我仍在寻找一种方法从日志视图中删除这些重复提交。 - Wivlaro
1
@Wivlaro 很不幸,我看不到其他的选择了。几个月前我曾追踪这种行为,深入研究了一下 Git 的源代码。我没有看到过滤补丁和提交 ID 的选项。 :-( - John Szakmeister
@jszakmeister 我也被这个问题困扰。我的工作流程是主分支跟踪上游,开发分支定期合并主分支,功能分支基于开发分支。完成功能后,主分支拉取最新的上游代码,开发分支合并它,将功能分支变基到新的开发分支上,创建一个指向功能分支的新分支'ready-for-review',并将其变基到主分支上。在它被包含在上游之后,开发分支合并更新的主分支和功能分支。因此,会有两个重复的提交,一个来自主分支,一个来自功能分支,但开发分支也有不在主分支中的提交,需要显示出来。 - weynhamz
1
@TechliveZheng 这绝对是可能的,而且我认为它足够简单。我认为最大的障碍将是性能问题。这意味着你需要同时搜索补丁 ID 和提交 ID,而这可能会导致性能下降到 Git 项目可能无法接受的程度。这并不像性能下降了50%那么简单明了,因为你只需要检查在任一方面都不存在的提交的补丁 ID。我觉得值得在 Git 邮件列表上提出这个问题。 - John Szakmeister
显示剩余10条评论

2
“我经常想知道git是否应该始终检查两者,但这可能会导致相当大的性能损失。” “这种行为现在比以前更快了(Git 2.11,2016年第四季度)。”
查看提交 7c81040(2016年9月12日)和提交 5a29cbc(2016年9月9日),作者为Jeff King(peff
协助者:Johannes Schindelin(dscho
(由Junio C Hamano -- gitster --提交 f0a84de中合并,2016年9月21日) “patch-ids”:拒绝计算合并提交的“patch-id”。之前,“git log --cherry-pick”会将合并提交包含在待匹配提交的候选项中,导致了很多时间的浪费。现已更新“patch-id”生成逻辑以忽略合并提交,避免浪费时间。为了避免计算这些合并差异所花费的额外时间,本补丁的灵感来自于一个例子:“git format-patch --cherry-pick”从原本需要超过3分钟的时间缩短至不到3秒钟。
而且,在Git 2.31(2021年第一季度)中已经修复:当一个侧面上出现多个具有相同补丁ID的提交时,"git log --cherry-pick A...B"(man) 现在会排除所有这些提交,如果另一个侧面出现了相同补丁ID的提交。

2
我使用的是Git 2.35版本,除非我误解了,否则它似乎对我没有修复。要复制:我有两个分支,devmasterdevmaster领先1个提交,因此我将该提交cherry-pick到master,然后将master合并到dev。然后运行git log --cherry-pick master...dev,原始提交仍然显示出来,即使它具有与cherry-pick提交相同的patch-id。 - André T.
@AndréT。有趣。你能否提出一个单独的问题来说明这种情况和错误?此外,2.37就在不远处了。 - VonC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接