简体中文 ▾ 主题 ▾ 最新版本 ▾ git-shortlog 上次更新于 2.52.0

名称

git-shortlog - 汇总 git log 输出

概要

git shortlog [<options>] [<revision-range>] [[--] <path>…​]
git log --pretty=short | git shortlog [<options>]

描述

以适合包含在发布公告中的格式汇总 git log 输出。每个提交将按作者和标题分组。

此外,“[PATCH]”将从提交描述中剥离。

如果在命令行中未传递任何修订版本,并且标准输入不是终端,或者当前不存在分支,git shortlog 将输出从标准输入读取的日志摘要,而不引用当前存储库。

选项

-n
--numbered

按每位作者的提交次数对输出进行排序,而不是按作者字母顺序排序。

-s
--summary

禁止显示提交描述,仅提供提交计数摘要。

-e
--email

显示每位作者的电子邮件地址。

--format[=<format>]

代替提交主题,使用其他信息来描述每个提交。<format> 可以是 git log--format 选项接受的任何字符串,例如 * [%h] %s。(参见 git-log[1] 的“PRETTY FORMATS”部分。)

每个美化打印的提交在显示前都将被重新包装。

--date=<format>

按照给定的日期字符串格式化日期。(参见 git-log[1] 的“Commit Formatting”部分的 --date 选项)。与 --group=format:<format> 结合使用很有用。

--group=<type>

根据 <type> 对提交进行分组。如果未指定 --group 选项,则默认为 author<type> 是以下之一:

  • author,按作者分组提交

  • committer,按提交者分组提交(与 -c 相同)

  • trailer:<field><field> 被解释为不区分大小写的提交消息尾注(参见 git-interpret-trailers[1])。例如,如果你的项目使用 Reviewed-by 尾注,你可能想通过 git shortlog -ns --group=trailer:reviewed-by 查看谁在审查。

  • format:<format>git log--format 选项接受的任何字符串。(参见 git-log[1] 的“PRETTY FORMATS”部分。)

    请注意,不包含该尾注的提交将不会被计算。同样,具有多个尾注的提交(例如,多个签核)可能会被计算多次(但在该提交中仅按唯一的尾注值计算一次)。

    Shortlog 会尝试将每个尾注值解析为 name <email> 身份。如果成功,将应用 mailmap,除非指定了 --email 选项,否则电子邮件将被省略。如果值不能被解析为身份,它将被字面地、完整地接受。

如果多次指定 --group,提交将在每个值下进行计数(但同样,在提交中仅按唯一的组合值计算一次)。例如,git shortlog --group=author --group=trailer:co-authored-by 会同时计算作者和协作者。

-c
--committer

这是 --group=committer 的别名。

-w[<width>[,<indent1>[,<indent2>]]]

通过将每行包装到 width 来包装输出。每条条目的第一行缩进 indent1 个空格,第二行及后续行缩进 indent2 个空格。 widthindent1indent2 默认分别为 76、6 和 9。

如果 width 为 0(零),则缩进输出行而不进行换行。

<revision-range>

仅显示指定修订范围内的提交。当未指定 <revision-range> 时,默认为 HEAD(即直到当前提交的整个历史)。origin..HEAD 指定了所有可从当前提交(即 HEAD)到达但不能从 origin 到达的提交。有关指定 <revision-range> 的完整列表,请参阅 gitrevisions[7] 的“Specifying Ranges”部分。

[--] <path>…

仅考虑足以解释匹配指定路径的文件如何形成的提交。

当出现混淆时,路径可能需要用 -- 作为前缀,以将其与选项或修订范围分开。

提交限制

除了使用描述中解释的特殊符号指定应列出的提交范围外,还可以应用额外的提交限制。

使用更多选项通常会进一步限制输出(例如,--since=<date1> 限制为比 <date1> 更新的提交,并且将其与 --grep=<pattern> 一起使用会进一步限制为其日志消息中有一行与 <pattern> 匹配的提交),除非另有说明。

请注意,这些是在提交排序和格式化选项(如 --reverse)之前应用的。

-<number>
-n <number>
--max-count=<number>

将输出限制为 <number> 个提交。

--skip=<number>

在开始显示提交输出之前,跳过 <number> 个提交。

--since=<date>
--after=<date>

显示比 <date> 更新的提交。

--since-as-filter=<date>

显示所有比 <date> 更新的提交。这会遍历范围内的所有提交,而不是在第一个比 <date> 旧的提交处停止。

--until=<date>
--before=<date>

显示比 <date> 旧的提交。

--author=<pattern>
--committer=<pattern>

将提交输出限制为作者/提交者标题行与 <pattern> 正则表达式匹配的提交。使用多个 --author=<pattern> 时,会选择作者匹配任何 <pattern> 的提交(对多个 --committer=<pattern> 类似)。

--grep-reflog=<pattern>

将提交输出限制为 reflog 条目与 <pattern> 正则表达式匹配的提交。使用多个 --grep-reflog 时,会选择 reflog 消息匹配任何给定模式的提交。使用此选项但未同时使用 --walk-reflogs 是错误的。

--grep=<pattern>

将提交输出限制为其日志消息匹配 <pattern> 正则表达式的提交。使用多个 --grep=<pattern> 时,会选择消息匹配任何 <pattern> 的提交(但请参阅 --all-match)。

--notes 生效时,来自备注的消息将像日志消息的一部分一样进行匹配。

--all-match

限制提交输出为匹配所有给定 --grep 的提交,而不是匹配至少一个的提交。

--invert-grep

将提交输出限制为其日志消息不匹配使用 --grep=<pattern> 指定的 <pattern> 的提交。

-i
--regexp-ignore-case

匹配正则表达式限制模式时不区分字母大小写。

--basic-regexp

将限制模式视为基本正则表达式;这是默认设置。

-E
--extended-regexp

将限制模式视为扩展正则表达式,而不是默认的基本正则表达式。

-F
--fixed-strings

将限制模式视为固定字符串(不将模式解释为正则表达式)。

-P
--perl-regexp

将限制模式视为 Perl 兼容的正则表达式。

对这些类型的正则表达式的支持是一个可选的编译时依赖项。如果 Git 在编译时没有支持这些功能,则提供此选项将导致其停止运行。

--remove-empty

当给定路径从树中消失时停止。

--merges

只打印合并提交。这与 --min-parents=2 完全相同。

--no-merges

不打印具有多个父提交的提交。这与 --max-parents=1 完全相同。

--min-parents=<number>
--max-parents=<number>
--no-min-parents
--no-max-parents

仅显示具有至少(或最多)该数量父提交的提交。特别是,--max-parents=1 等同于 --no-merges--min-parents=2 等同于 --merges--max-parents=0 显示所有根提交,--min-parents=3 显示所有八爪鱼合并。

--no-min-parents--no-max-parents 再次重置这些限制(设置为无限制)。等效形式为 --min-parents=0(任何提交都有 0 个或多个父提交)和 --max-parents=-1(负数表示无上限)。

--first-parent

在查找要包含的提交时,遇到合并提交时仅跟随第一个父提交。此选项在查看特定主题分支的演变时可能提供更好的概览,因为合并到主题分支通常只是为了调整上游的更新,并且此选项允许您忽略此类合并带来的历史中的单个提交。

--exclude-first-parent-only

在查找要排除的提交(使用 ^)时,遇到合并提交时仅跟随第一个父提交。当给定任意合并可以是有效主题分支更改时,这可用于查找主题分支从其与远程分支分叉的点开始的更改集。

--not

反转所有后续修订说明符中的 ^ 前缀(或缺乏前缀)的含义,直到下一个 --not。当在命令行上使用 --stdin 之前时,通过 stdin 传递的修订不会受其影响。反之,当通过标准输入传递时,在命令行上通过的修订不会受其影响。

--all

假装 refs/ 中的所有引用以及 HEAD 都已在命令行上列为 <commit>

--branches[=<pattern>]

假装 refs/heads 中的所有引用都已在命令行上列为 <commit>。如果给出了 <pattern>,则将分支限制为与给定 shell glob 匹配的分支。如果 <pattern> 缺少 ?*[,则在末尾隐含 /*

--tags[=<pattern>]

假装 refs/tags 中的所有引用都已在命令行上列为 <commit>。如果给出了 <pattern>,则将标签限制为与给定 shell glob 匹配的标签。如果模式缺少 ?*[,则在末尾隐含 /*

--remotes[=<pattern>]

假装 refs/remotes 中的所有引用都已在命令行上列为 <commit>。如果给出了 <pattern>,则将远程跟踪分支限制为与给定 shell glob 匹配的分支。如果模式缺少 ?*[,则在末尾隐含 /*

--glob=<glob-pattern>

假装所有匹配 shell glob <glob-pattern> 的引用都已在命令行上列为 <commit>。如果缺少,则自动加上前缀 refs/。如果模式缺少 ?*[,则在末尾隐含 /*

--exclude=<glob-pattern>

不包括与下一个 --all--branches--tags--remotes--glob 将要考虑的 <glob-pattern> 匹配的引用。此选项的重复使用会累积排除模式,直到下一个 --all--branches--tags--remotes--glob 选项(其他选项或参数不会清除累积的模式)。

当应用于 --branches--tags--remotes 时,给出的模式不应分别以 refs/headsrefs/tagsrefs/remotes 开头,并且当应用于 --glob--all 时,它们必须以 refs/ 开头。如果要匹配结尾的 /*,则必须显式给出。

--exclude-hidden=(fetch|receive|uploadpack)

通过查阅适当的 fetch.hideRefsreceive.hideRefsuploadpack.hideRefs 配置以及 transfer.hideRefs(请参阅 git-config[1]),不包括会被 git-fetchgit-receive-packgit-upload-pack 隐藏的引用。此选项会影响下一个伪引用选项 --all--glob,并在处理它们之后清除。

--reflog

假装由 reflog 提及的所有对象都已在命令行上列为 <commit>

--alternate-refs

假装备用存储库的引用尖端中提到的所有对象都已在命令行上列出。备用存储库是其对象目录在 objects/info/alternates 中指定的任何存储库。包含的对象集可能由 core.alternateRefsCommand 等修改。请参阅 git-config[1]

--single-worktree

默认情况下,当存在多个工作树时(请参阅 git-worktree[1]),以下选项将检查所有工作树:--all--reflog--indexed-objects。此选项强制它们仅检查当前工作树。

--ignore-missing

在输入中遇到无效对象名称时,假装没有给出错误的输入。

--bisect

假装坏二分查找引用 refs/bisect/bad 已列出,并且假装它后面跟着 --not 和好二分查找引用 refs/bisect/good-* 在命令行上。

--stdin

除了从命令行获取参数外,还可以从标准输入读取它们。这接受提交和伪选项,如 --all--glob=。当看到 -- 分隔符时,后面的输入被视为路径并用于限制结果。通过 stdin 读取的标志(如 --not)仅对以相同方式传递的参数有效,并且不会影响任何后续命令行参数。

--cherry-mark

类似于 --cherry-pick(见下文),但用 = 标记等效提交而不是省略它们,用 + 标记不等效提交。

--cherry-pick

当提交集合通过对称差异限制时,省略与“另一侧”的另一个提交引入相同更改的任何提交。

例如,如果您有两个分支 AB,列出它们其中一个分支上所有提交的常用方法是使用 --left-right(请参阅下面的 --left-right 选项的说明中的示例)。但是,它会显示从另一个分支 cherry-pick 的提交(例如,“b 上的第 3 个”可能从分支 A cherry-pick)。使用此选项,将从输出中排除此类提交对。

--left-only
--right-only

仅列出对称差集一侧的提交,即仅那些由 --left-right 标记为 <> 的提交。

例如,--cherry-pick --right-only A...B 将 B 中在 A 中或与 A 中的提交补丁等效的提交从 B 中省略。换句话说,这列出了 git cherry A B 中的 + 提交。更精确地说,--cherry-pick --right-only --no-merges 提供了确切列表。

--cherry

--right-only --cherry-mark --no-merges 的同义词;对于限制我们这边的提交很有用,并标记那些已被应用于分叉历史的另一边,使用 git log --cherry upstream...mybranch,类似于 git cherry upstream mybranch

-g
--walk-reflogs

不是遍历提交祖先链,而是从最近的一个到较旧的一个遍历 reflog 条目。使用此选项时,您不能指定要排除的提交(即,不能使用 ^<commit><commit1>..<commit2><commit1>...<commit2> 表示法)。

使用 --pretty 格式(onelinereference 除外,原因显而易见),这会导致输出包含来自 reflog 的两行额外信息。输出中的 reflog 标识符可能显示为 ref@{<Nth>}(其中 <Nth> 是 reflog 中按时间倒序的索引)或 ref@{<timestamp>}(带有该条目的 <timestamp>),具体取决于一些规则。

  1. 如果起始点指定为 ref@{<Nth>},则显示索引格式。

  2. 如果起始点指定为 ref@{now},则显示时间戳格式。

  3. 如果两者都未用,但命令行上给出了 --date,则以 --date 请求的格式显示时间戳。

  4. 否则,显示索引格式。

--pretty=oneline 下,提交消息在该行上以这些信息为前缀。此选项不能与 --reverse 结合使用。另请参阅 git-reflog[1]

--pretty=reference 模式下,此信息将完全不显示。

--merge

显示在 HEAD...<other> 范围内接触已冲突路径的提交,其中 <other>MERGE_HEADCHERRY_PICK_HEADREVERT_HEADREBASE_HEAD 中的第一个存在的伪引用。仅当索引包含未合并条目时才有效。此选项可用于在解决 3 路合并冲突时显示相关提交。

--boundary

输出排除的边界提交。边界提交前缀为 -

历史简化

有时您只对历史的一部分感兴趣,例如修改特定 <path> 的提交。但是,"历史简化" 有两个部分,一部分是选择提交,另一部分是如何选择,因为存在各种简化历史的策略。

以下选项选择要显示的提交

<paths>

选择修改给定 <paths> 的提交。

--simplify-by-decoration

选择被某些分支或标签引用的提交。

请注意,可以显示额外的提交以提供有意义的历史记录。

以下选项影响简化执行的方式

默认 模式

将历史简化为解释树最终状态的最简单历史。之所以最简单,是因为如果最终结果相同(即合并内容相同的分支),它会修剪一些旁支。

--show-pulls

包含默认模式中的所有提交,但也包括任何与第一个父提交不 TREESAME 但与较晚的父提交 TREESAME 的合并提交。此模式有助于显示“首次引入”更改到分支的合并提交。

--full-history

与默认模式相同,但不会修剪某些历史。

--dense

只显示选定的提交,以及一些具有有意义历史的提交。

--sparse

显示简化历史中的所有提交。

--simplify-merges

--full-history 的附加选项,用于从结果历史中删除一些不必要的合并,因为没有选定的提交对此合并有所贡献。

--ancestry-path[=<commit>]

当给定一个要显示的提交范围(例如 <commit1>..<commit2><commit2> ^<commit1>),以及该范围内的提交 <commit> 时,只显示在该范围内是 <commit> 的祖先、<commit> 的后代,或者 <commit> 本身的提交。如果没有指定提交,则将 <commit1>(范围中排除的部分)用作 <commit>。可以多次传递;如果是这样,如果一个提交是给定的任何提交之一,或者它是其中一个的祖先或后代,则包含该提交。

更详细的解释如下。

假设您指定了 foo 作为 <paths>。我们将调用修改 foo 的提交为 !TREESAME,其余的为 TREESAME。(在为 foo 过滤的 diff 中,它们分别看起来不同和相同。)

在下文中,我们将始终引用相同的历史示例来阐述简化设置之间的差异。我们假设您正在此提交图中过滤文件 foo

	  .-A---M---N---O---P---Q
	 /     /   /   /   /   /
	I     B   C   D   E   Y
	 \   /   /   /   /   /
	  `-------------'   X

历史记录的水平线 A---Q 被视为每个合并的第一个父级。提交是

  • I 是初始提交,其中 foo 存在,内容为 asdf,并且文件 quux 存在,内容为 quux。初始提交与空树进行比较,因此 I 是 !TREESAME。

  • A 中,foo 只包含 foo

  • B 包含与 A 相同的更改。其合并 M 是微不足道的,因此与所有父级 TREESAME。

  • C 没有改变 foo,但其合并 N 将其更改为 foobar,因此它与任何父项都不同(!TREESAME)。

  • Dfoo 设置为 baz。其合并 OND 的字符串合并为 foobarbaz;即,它与任何父项都不同(!TREESAME)。

  • Equux 更改为 xyzzy,其合并 P 将字符串合并为 quux xyzzyPO 是 TREESAME,但与 E 不是。

  • X 是一个独立的根提交,它添加了一个新文件 side,而 Y 修改了它。YX 是 TREESAME。其合并 Qside 添加到 P,而 QP 是 TREESAME,但与 Y 不是。

rev-list 向后遍历历史记录,根据是否使用了 --full-history 和/或父项重写(通过 --parents--children)来包含或排除提交。以下是可用的设置。

默认模式

包含的提交是那些与任何父项都不同的提交(尽管这可以改变,请参见下文的 --sparse)。如果提交是合并,并且它与一个父项是 TREESAME,则只跟随该父项。(即使有多个 TREESAME 父项,也只跟随其中一个。)否则,跟随所有父项。

这导致

	  .-A---N---O
	 /     /   /
	I---------D

请注意,如果存在 TREESAME 父项,则只跟随该 TREESAME 父项的规则如何使 B 完全被排除。 C 是通过 N 考虑的,但它是 TREESAME。根提交与空树进行比较,因此 I 是 !TREESAME。

父/子关系仅在 --parents 选项下可见,但这不影响默认模式下选择的提交,因此我们已显示父行。

--full-history 无父重写

此模式与默认模式仅有一处不同:总是跟随合并的所有父项,即使它与其中一个父项是 TREESAME。即使合并的多个分支都包含提交,这也不意味着合并本身会被包含!在示例中,我们得到:

	I  A  B  N  D  O  P  Q

M 被排除是因为它与两个父项都是 TREESAME。 ECB 都被遍历,但只有 B 是 !TREESAME,因此其他的不出现。

请注意,如果没有父级重写,很难真正谈论提交之间的父/子关系,因此我们将它们显示为断开连接。

--full-history 带父重写

普通提交仅在它们是 !TREESAME 时才包含(尽管这可以更改,请参阅下面的 --sparse)。

合并总是被包含。然而,它们的父列表被重写:沿每个父列表,修剪掉本身未包含的提交。这导致

	  .-A---M---N---O---P---Q
	 /     /   /   /   /
	I     B   /   D   /
	 \   /   /   /   /
	  `-------------'

与上面的“不进行父项重写的 --full-history”进行比较。请注意,E 被删除了,因为它本身是 TREESAME,但 P 的父项列表被重写为包含 E 的父项 I。对于 CN,以及 XYQ,也发生了同样的情况。

除了上述设置之外,您还可以更改 TREESAME 是否影响包含

--dense

被遍历的提交如果与任何父级都不是 TREESAME,则会被包含。

--sparse

所有被遍历的提交都将被包含。

请注意,没有 --full-history,这仍然会简化合并:如果其中一个父级是 TREESAME,我们只跟踪那一个,因此合并的其他侧永远不会被遍历。

--simplify-merges

首先,以与 --full-history 带父级重写相同的方式构建历史图(见上文)。

然后根据以下规则将每个提交 C 简化为其在最终历史记录中的替换 C'

  • C' 设置为 C

  • C' 的每个父项 P 替换为其简化后的 P'。在此过程中,删除是其他父项的祖先或与空树 TREESAME 的根提交的父项,并删除重复项,但注意永远不要删除所有我们是 TREESAME 的父项。

  • 如果在此父重写之后,C' 是一个根提交或合并提交(具有零或 >1 个父级),一个边界提交,或 !TREESAME,则它保持不变。否则,它将被其唯一父级替换。

通过与带父重写的 --full-history 进行比较,最能体现其效果。示例变为

	  .-A---M---N---O
	 /     /       /
	I     B       D
	 \   /       /
	  `---------'

注意 NPQ 相对于 --full-history 的主要区别:

  • N 的父项列表中删除了 I,因为它是另一个父项 M 的祖先。但是,N 仍然被保留,因为它与任何父项都不同(!TREESAME)。

  • P 的父列表类似地移除了 IP 随后被完全移除,因为它有一个父级且是 TREESAME。

  • Q 的父项列表将 Y 简化为 XX 然后被删除,因为它是一个 TREESAME 的根提交。Q 然后被完全删除,因为它只有一个父项并且是 TREESAME。

还有另一种简化模式可用

--ancestry-path[=<commit>]

将显示的提交限制为 <commit> 的祖先,或者 <commit> 的后代,或者 <commit> 本身的提交。

作为一个示例用例,考虑以下提交历史:

	    D---E-------F
	   /     \       \
	  B---C---G---H---I---J
	 /                     \
	A-------K---------------L--M

常规的 D..M 计算 M 的祖先的提交集,但排除 D 的祖先的提交。这对于查看自 D 以来 M 的历史记录中发生了什么非常有用,从“M 拥有 D 中不存在的什么”的意义上来说。在此示例中的结果将是所有提交,除了 A 和 B(以及 D 本身,当然)。

然而,当我们想找出 M 中的哪些提交受到了 D 引入的 bug 的污染并需要修复时,我们可能只想查看 D..M 中实际上是 D 的后代的提交子集,即排除 C 和 K。这正是 `--ancestry-path` 选项的作用。应用于 D..M 范围,结果是:

		E-------F
		 \       \
		  G---H---I---J
			       \
				L--M

我们也可以使用 `--ancestry-path=D` 而不是 `--ancestry-path`,当应用于 D..M 范围时,它的含义相同,只是更明确。

如果我们更关注该范围内的某个特定主题及其所有受影响的提交,我们可能只想查看 D..M 中包含该主题的祖先路径的提交子集。因此,例如使用 `--ancestry-path=H D..M` 会导致:

		E
		 \
	      C---G---H---I---J
			       \
				L--M

--ancestry-path=K D..M 将会得到:

		K---------------L--M

在讨论另一个选项 --show-pulls 之前,我们需要创建一个新的示例历史记录。

用户在查看简化历史时遇到的一个常见问题是,他们知道修改了某个文件的提交实际上并没有出现在该文件的简化历史中。让我们展示一个新示例,看看 `--full-history` 和 `--simplify-merges` 等选项在这种情况下是如何工作的。

	  .-A---M-----C--N---O---P
	 /     / \  \  \/   /   /
	I     B   \  R-'`-Z'   /
	 \   /     \/         /
	  \ /      /\        /
	   `---X--'  `---Y--'

对于这个例子,假设 I 创建了 file.txt,该文件被 ABX 以不同的方式修改。单父提交 CZY 不会改变 file.txt。合并提交 M 是通过解析合并冲突而创建的,以包含来自 AB 的所有更改,因此它与两者都不同(不是 TREESAME)。然而,合并提交 R 是通过忽略 M 时的 file.txt 内容而创建的,只取 X 时的 file.txt 内容。因此,RX 是 TREESAME,但与 M 不是。最后,创建 N 的自然合并解析是采用 R 时的 file.txt 内容,所以 NR 是 TREESAME,但与 C 不是。合并提交 OP 分别与它们的第一个父提交(ZY)是 TREESAME,但与它们的第二个父提交(ZY)不是。

在使用默认模式时,NR 都具有一个 TREESAME 父级,因此那些边缘被遍历,而其他的则被忽略。生成的历史图是

	I---X

使用 `--full-history` 时,Git 会遍历每个边。这将发现提交 A 和 B 以及合并 M,但也会显示合并提交 O 和 P。使用父项重写后,生成的图是:

	  .-A---M--------N---O---P
	 /     / \  \  \/   /   /
	I     B   \  R-'`--'   /
	 \   /     \/         /
	  \ /      /\        /
	   `---X--'  `------'

在这里,合并提交 O 和 P 贡献了额外的噪音,因为它们实际上没有为 `file.txt` 贡献更改。它们只是合并了一个基于旧版本 `file.txt` 的主题。这是在许多贡献者并行工作并将主题分支合并到单条主线的工作流中常见的存储库问题:许多不相关的合并出现在 `--full-history` 的结果中。

当使用 `--simplify-merges` 选项时,提交 O 和 P 将从结果中消失。这是因为 O 和 P 的重写后的第二个父项可以从它们的第一个父项到达。这些边被移除,然后这些提交看起来像单父提交,并且与它们的父项是 TREESAME。提交 N 也发生这种情况,导致历史视图如下:

	  .-A---M--.
	 /     /    \
	I     B      R
	 \   /      /
	  \ /      /
	   `---X--'

在此视图中,我们看到了 A、B 和 X 的所有重要的单父提交更改。我们还看到了仔细解析的合并 M 和不太仔细解析的合并 R。这通常足以确定为什么提交 A 和 B 在默认视图中“消失”了。但是,此方法存在一些问题。

第一个问题是性能。与之前的任何选项不同,`--simplify-merges` 选项在返回单个结果之前需要遍历整个提交历史。这使得该选项对于非常大的存储库难以使用。

第二个问题是审计。当许多贡献者在同一个存储库中工作时,哪个合并提交将更改引入重要分支是很重要的。上面的有问题的合并 R 很可能不是用于将 R 合并到重要分支的合并提交。相反,合并 N 用于将 R 和 X 合并到重要分支。该提交可能包含有关 X 的更改覆盖 A 和 B 的更改原因的信息。

--show-pulls

除了默认历史中显示的提交外,显示每个与其第一个父级不是 TREESAME 但与其后续父级是 TREESAME 的合并提交。

当合并提交被 `--show-pulls` 包含时,合并被视为“拉取”了另一个分支的更改。当在此示例上使用 `--show-pulls`(且没有其他选项)时,生成的图是:

	I---X---R---N

在这里,合并提交 R 和 N 被包含,因为它们分别拉取了提交 X 和 R 到主分支。这些合并是提交 A 和 B 不出现在默认历史记录中的原因。

--show-pulls--simplify-merges 配对使用时,图表包含所有必要的信息

	  .-A---M--.   N
	 /     /    \ /
	I     B      R
	 \   /      /
	  \ /      /
	   `---X--'

请注意,由于 M 可以从 R 到达,因此从 N 到 M 的边被简化掉了。然而,N 仍然作为重要的提交出现在历史记录中,因为它将更改 R “拉取”到了主分支。

`--simplify-by-decoration` 选项允许您仅查看历史拓扑的大图,通过省略未被标签引用的提交。当(1)它们被标签引用,或(2)它们更改了命令行上给定的路径的内容时,提交被标记为 !TREESAME(换句话说,在上述历史简化规则后保留)。所有其他提交被标记为 TREESAME(可能被简化掉)。

作者映射

请参阅 gitmailmap[5]

注意,如果在存储库外部运行 git shortlog(用于处理标准输入上的日志内容),它会在当前目录中查找 .mailmap 文件。

GIT

Git[1] 套件的一部分