我如何使用 git cherry 来获取提交者的电子邮件?

How do I use git cherry to get committer email?

git cherry 在获取两个分支之间的差异方面优于 git log。问题是它的输出是有限的。

我正在尝试提取与提交关联的电子邮件地址(或用户)。这就是我正在做的。

git cherry firstbranch secondbranch | awk '/^+/ {print }' | awk '{ system("git show "); }'

我得到的只是一次提交的详细信息。而不是我所做的每一次提交:

git cherry firstbranch secondbranch | awk '/^+/ {print }'

第二个管道操作出现问题。

我的问题是:如何使用 git cherry 获取提交者电子邮件?

像这样:

git cherry firstbranch secondbranch | awk '[=10=]=' | git log --no-walk --stdin --pretty='%h %ce'
  1. --no-walk:只显示给定的提交,但不遍历它们的祖先

  2. %h:缩写提交哈希

  3. %ce: 提交者邮箱

Source

git log --no-walk --stdin 的管道是一种正确的方法,并且在最复杂的情​​况下是必需的(对选定的提交 ID 进行复杂过滤)。

不过,对于这个特殊的案例,有一些技巧可以使用。如果你检查(广泛的,尽管令人困惑)documentation for git rev-list,你会发现选项 --left-right--left-only--right-only--cherry-mark--cherry-pick、和 --cherry.

--left-right 选项适用于任何对称差异,即由 A...B 选择的提交,这意味着 "all commits that are on branch A or branch B, excluding any commits that are on both branches." 这就是 git cherry 执行其第一部分的方式事情:它发现在对称差异上的提交。但是,git cherry 继续 丢弃 所有 "the same"1[= 的提交98=] 在两个分支上,然后用 - 标记一侧,用 + 标记另一侧的那些。 --left-right 选项将所有提交标记为 <(左侧)或 >(右侧)。

由于 rev-list 是 Swiss Army Chainsaw 命令,它 有能力抛出相同的提交。它还有更多的能力:它可以完全抛出一侧的提交,相同或不同。这就是我们在这种情况下想要的:扔掉 "commits that are the same"(这样我们只保留 "different" 个),然后扔掉所有 "left side" 提交(这样我们只保留那些在右侧而不是左侧)。我们用 --cherry-pick 得到前者:它只保留被认为是 "different" 的提交。然后我们添加 --right-only 以仅保留右侧的那些,即当我们说 firstbranch...secondbranch 时,仅保留 [=36] 中 不同的那些=] ...这正是 git cherry 所做的。

因此:

git rev-list --right-only --cherry-pick firstbranch...secondbranch

生成与以下相同的提交 ID 列表:

git cherry firstbranch secondbranch

(唯一的区别是它打印 +face0ff 而不是 + face0ff...,即 + 标记后没有 space。

这看起来很傻:我们需要 git rev-list 和一堆选项、两个分支名称和三个句点,而不是四个单词 git cherry 和两个分支名称。我们输入了更多的字母以获得几乎相同的结果。所以我们可以只使用较短的命令并将其通过管道传输到 git log,但现在我们到了棘手的一点。

git loggit rev-list 几乎是相同的命令

事实上,它们是从相同的源代码构建的,它们只是设置了一些不同的内部选项(如果你不指定任何其他起点,git log 会假装你说 HEAD ).由于我们即将将 git rev-list 的输出通过管道传输到 git log --pretty='%h %ce',也许我们可以直接在 git log 中完成所有操作。

果然可以。我们需要所有与 git rev-list 相同的选项,但现在我们只需 运行:

git log --cherry-pick --right-only --pretty='%h %ce' firstbranch...secondbranch

(您可能还需要 --no-merges——我不确定 git cherry 对合并做了什么!)。


1"Sameness",在这种情况下,由 git patch-id 的输出决定,它基本上从差异中去除识别行号(并且也去除某些白色 space 细节)。因此,如果一个提交被挑选到另一个分支中,那么这两个提交通常将具有相同的补丁 ID。 (如果有人必须解决合并冲突,补丁 ID 会有所不同。)