设置和配置
获取和创建项目
基本快照
分支与合并
共享和更新项目
检查和比较
打补丁
调试
电子邮件
外部系统
服务器管理
指南
管理
底层命令
- 2.50.1 无更改
-
2.50.0
2025-06-16
- 2.49.1 无更改
-
2.49.0
2025-03-14
- 2.48.1 → 2.48.2 无更改
-
2.48.0
2025-01-10
- 2.45.1 → 2.47.3 无更改
-
2.45.0
2024-04-29
- 2.43.3 → 2.44.4 无更改
-
2.43.2
2024-02-13
- 2.43.1 无变更
-
2.43.0
2023-11-20
- 2.42.1 → 2.42.4 无更改
-
2.42.0
2023-08-21
- 2.41.1 → 2.41.3 无更改
-
2.41.0
2023-06-01
- 2.40.1 → 2.40.4 无更改
-
2.40.0
2023-03-12
- 2.39.1 → 2.39.5 无变化
-
2.39.0
2022-12-12
- 2.38.1 → 2.38.5 无更改
-
2.38.0
2022-10-02
- 2.37.1 → 2.37.7 无更改
-
2.37.0
2022-06-27
- 2.36.1 → 2.36.6 无更改
-
2.36.0
2022-04-18
- 2.35.1 → 2.35.8 无更改
-
2.35.0
2022-01-24
- 2.33.3 → 2.34.8 无变更
-
2.33.2
2022-03-23
-
2.33.1
2021-10-12
-
2.33.0
2021-08-16
- 2.32.1 → 2.32.7 无变更
-
2.32.0
2021-06-06
- 2.31.1 → 2.31.8 无更改
-
2.31.0
2021-03-15
- 2.30.1 → 2.30.9 无更改
-
2.30.0
2020-12-27
- 2.29.1 → 2.29.3 无更改
-
2.29.0
2020-10-19
- 2.27.1 → 2.28.1 无变更
-
2.27.0
2020-06-01
- 2.25.1 → 2.26.3 无更改
-
2.25.0
2020-01-13
- 2.18.1 → 2.24.4 无更改
-
2.18.0
2018-06-21
- 2.13.7 → 2.17.6 无更改
-
2.12.5
2017-09-22
- 2.1.4 → 2.11.4 无更改
-
2.0.5
2014-12-17
概要
git shortlog [<options>] [<revision-range>] [[--] <path>…] git log --pretty=short | git shortlog [<options>]
描述
以适合包含在发布公告中的格式总结 git log 输出。每个提交将按作者和标题分组。
此外,"[PATCH]" 将从提交描述中去除。
如果命令行上没有传递修订版本,并且标准输入不是终端或没有当前分支,git shortlog 将输出从标准输入读取的日志摘要,而不参考当前仓库。
选项
- -n
- --numbered
-
根据每位作者的提交数量而不是作者字母顺序排序输出。
- -s
- --summary
-
抑制提交描述,仅提供提交计数摘要。
- -e
-
显示每位作者的电子邮件地址。
- --format[=<format>]
-
不使用提交主题,而是使用其他信息来描述每个提交。<format> 可以是 git log 的
--format
选项接受的任何字符串,例如 * [%h] %s。(请参阅 git-log[1] 的“PRETTY FORMATS”部分。)Each pretty-printed commit will be rewrapped before it is shown.
- --date=<format>
-
按给定日期字符串格式显示日期。(请参阅 git-log[1] 的“提交格式化”部分的
--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> 身份。如果成功,则应用邮件映射,并且除非指定了--email
选项,否则将省略电子邮件。如果该值无法解析为身份,它将被按字面意义完整地处理。
如果多次指定
--group
,则提交将在每个值下计算(但同样,在该提交中,每个唯一值仅计算一次)。例如,git
shortlog
--group=author
--group=trailer:co-authored-by
会同时计算作者和合著作者。 -
- -c
- --committer
-
这是
--group=committer
的别名。 - -w[<width>[,<indent1>[,<indent2>]]]
-
通过在
width
处换行来对输出进行行包装。每个条目的第一行缩进indent1
个空格,第二行及后续行缩进indent2
个空格。width
、indent1
和indent2
默认分别为 76、6 和 9。如果宽度为
0
(零),则缩进输出行而不对其进行包装。 - <revision-range>
-
仅显示指定修订范围内的提交。当未指定 <revision-range> 时,默认为
HEAD
(即导致当前提交的整个历史)。origin..HEAD
指定所有从当前提交(即HEAD
)可达,但不可从origin
可达的提交。有关指定 <revision-range> 的完整方法列表,请参阅 gitrevisions[7] 的“指定范围”部分。 - [--] <path>…
-
仅考虑足以解释指定路径匹配的文件是如何形成的提交。
当可能发生混淆时,路径可能需要加上
--
前缀,以将其与选项或修订范围分隔开。
提交限制
除了使用描述中解释的特殊符号指定应列出的提交范围外,还可以应用额外的提交限制。
使用更多选项通常会进一步限制输出(例如,--since=
<date1> 限制为晚于 <date1> 的提交,而将其与 --grep=
<pattern> 一起使用则进一步限制为日志消息中包含与 <pattern> 匹配的行的提交),除非另有说明。
请注意,这些是在提交排序和格式化选项(如 --reverse
)之前应用的。
- -<number>
- -n <number>
- --max-count=<number>
-
限制输出的提交数量。
- --skip=<number>
-
在开始显示提交输出之前跳过 number 个提交。
- --since=<date>
- --after=<date>
-
显示特定日期之后的所有提交。
- --since-as-filter=<date>
-
显示特定日期之后的所有提交。这将遍历范围内的所有提交,而不是在遇到第一个比特定日期更旧的提交时停止。
- --until=<date>
- --before=<date>
-
显示特定日期之前的所有提交。
- --author=<pattern>
- --committer=<pattern>
-
限制输出提交,使其作者/提交者头行与指定模式(正则表达式)匹配。当有多个
--author=
<pattern> 时,选择作者匹配任意给定模式的提交(多个--committer=
<pattern> 同理)。 - --grep-reflog=<pattern>
-
限制输出提交,使其 reflog 条目与指定模式(正则表达式)匹配。当有多个
--grep-reflog
时,选择 reflog 消息匹配任意给定模式的提交。除非使用了--walk-reflogs
,否则使用此选项是错误的。 - --grep=<pattern>
-
限制输出提交,使其日志消息与指定模式(正则表达式)匹配。当有多个
--grep=
<pattern> 时,选择消息匹配任意给定模式的提交(但请参阅--all-match
)。当
--notes
生效时,来自备注的消息将像日志消息的一部分一样进行匹配。 - --all-match
-
限制提交输出为匹配所有给定
--grep
的提交,而不是匹配至少一个的提交。 - --invert-grep
-
限制提交输出为日志消息不匹配由
--grep=
<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 的分支。如果模式缺少 ?、* 或 [,则默认为末尾的 /*。 - --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>
-
不包括与 <glob-pattern> 匹配的引用,这些引用否则会被下一个
--all
、--branches
、--tags
、--remotes
或--glob
考虑。此选项的重复使用会累积排除模式,直到下一个--all
、--branches
、--tags
、--remotes
或--glob
选项(其他选项或参数不会清除累积的模式)。应用于
--branches
、--tags
或--remotes
时,给定的模式不应以refs/heads
、refs/tags
或refs/remotes
开头;应用于--glob
或--all
时,它们必须以refs/
开头。如果需要尾随的 /*,则必须明确给出。 -
通过查阅相应的
fetch.hideRefs
、receive.hideRefs
或uploadpack.hideRefs
配置以及transfer.hideRefs
(参见 git-config[1]),不包含那些会被git-fetch
、git-receive-pack
或git-upload-pack
隐藏的引用。此选项影响下一个伪引用选项--all
或--glob
,并在处理它们后清除。 - --reflog
-
假装引用日志中提及的所有对象都作为 <commit> 列在命令行上。
- --alternate-refs
-
假装所有在备用仓库的引用提示中提到的对象都列在命令行上。备用仓库是其对象目录在
objects/info/alternates
中指定的任何仓库。包含的对象集可以通过core.alternateRefsCommand
等修改。请参阅 git-config[1]。 - --single-worktree
-
默认情况下,当有多个工作树时(参见 git-worktree[1]),以下选项将检查所有工作树:
--all
、--reflog
和--indexed-objects
。此选项强制它们仅检查当前工作树。 - --ignore-missing
-
在输入中遇到无效对象名称时,假装没有给出错误的输入。
- --bisect
-
假装 bad bisection 引用
refs/bisect/bad
已列出,并且其后跟着--not
和 good bisection 引用refs/bisect/good-*
在命令行上。 - --stdin
-
除了从命令行获取参数外,也从标准输入读取。这接受提交和伪选项,如
--all
和--glob=
。当看到--
分隔符时,后续输入将被视为路径,并用于限制结果。通过标准输入读取的标志(如--not
)仅对以相同方式传递的参数生效,并且不会影响任何后续的命令行参数。 - --cherry-mark
-
类似于
--cherry-pick
(见下文),但用=
标记等效提交而不是省略它们,用+
标记不等效提交。 - --cherry-pick
-
当提交集合通过对称差异限制时,省略与“另一侧”的另一个提交引入相同更改的任何提交。
例如,如果您有两个分支
A
和B
,通常只列出其中一侧的所有提交的方法是使用--left-right
(参见下面--left-right
选项描述中的示例)。但是,它会显示从另一个分支拣选(cherry-picked)的提交(例如,“3rd on b”可能从分支 A 拣选)。使用此选项,此类提交对将从输出中排除。 - --left-only
- --right-only
-
仅列出对称差分相应侧的提交,即仅列出会被
--left-right
标记为 < 或 > 的那些提交。例如,
--cherry-pick
--right-only
A...B
会从B
中省略那些存在于A
中或与A
中的提交补丁等效的提交。换句话说,这会列出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
格式(除了oneline
和reference
,原因显而易见)时,这会导致输出包含来自 reflog 的额外两行信息。输出中的 reflog 标识符可以显示为ref@{
<Nth>}
(其中 <Nth> 是 reflog 中按时间倒序的索引)或显示为ref@{
<timestamp>}
(带有该条目的 <timestamp>),具体取决于以下规则:-
如果起始点指定为
ref@{
<Nth>}
,则显示索引格式。 -
如果起始点指定为
ref@{now}
,则显示时间戳格式。 -
如果两者都未用,但命令行上给出了
--date
,则以--date
请求的格式显示时间戳。 -
否则,显示索引格式。
在
--pretty=oneline
模式下,提交消息会以 reflog 信息作为同一行的前缀。此选项不能与--reverse
结合使用。另请参阅 git-reflog[1]。在
--pretty=reference
模式下,此信息将完全不显示。 -
- --merge
-
显示在
HEAD...
<other> 范围内触及冲突路径的提交,其中 <other> 是MERGE_HEAD
、CHERRY_PICK_HEAD
、REVERT_HEAD
或REBASE_HEAD
中第一个存在的伪引用。仅当索引有未合并条目时才有效。此选项可用于在解决三方合并冲突时显示相关提交。 - --boundary
-
输出排除的边界提交。边界提交前缀为
-
。
历史简化
有时你只对历史的一部分感兴趣,例如修改特定 <path> 的提交。但是 历史简化 有两个部分,一部分是选择提交,另一部分是如何进行,因为有各种策略可以简化历史。
以下选项选择要显示的提交
请注意,可以显示额外的提交以提供有意义的历史记录。
以下选项影响简化执行的方式
- 默认模式
-
将历史简化为解释树最终状态的最简单历史。之所以最简单,是因为如果最终结果相同(即合并内容相同的分支),它会修剪一些旁支。
- --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
过滤的差异中,它们分别看起来不同和相同。)
在下文中,我们将始终引用相同的历史示例来阐述简化设置之间的差异。我们假设您正在此提交图中过滤文件 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。 -
D
将foo
设置为“baz”。它的合并O
将N
和D
的字符串组合成“foobarbaz”;也就是说,它与任何父节点都不是 TREESAME。 -
E
将quux
更改为“xyzzy”,其合并P
将字符串组合为“quux xyzzy”。P
与O
是 TREESAME,但与E
不是。 -
X
是一个独立的根提交,它添加了一个新文件side
,Y
修改了它。Y
与X
是 TREESAME。它的合并Q
将side
添加到P
,Q
与P
是 TREESAME,但与Y
不是。
rev-list
反向遍历历史记录,根据是否使用 --full-history
和/或父重写(通过 --parents
或 --children
)来包含或排除提交。以下设置可用。
- 默认模式
-
如果提交与任何父级都不是 TREESAME,则包含它们(尽管这可以更改,请参阅下面的
--sparse
)。如果提交是合并,并且它与一个父级是 TREESAME,则只跟踪该父级。(即使有几个 TREESAME 父级,也只跟踪其中一个。)否则,跟踪所有父级。这导致
.-A---N---O / / / I---------D
请注意,只跟踪 TREESAME 父级(如果存在)的规则如何完全排除了
B
。通过N
考虑了C
,但它是 TREESAME。根提交与空树进行比较,因此I
为 !TREESAME。父/子关系仅在
--parents
选项下可见,但这不影响默认模式下选择的提交,因此我们已显示父行。 - --full-history 没有父重写
-
此模式与默认模式有一点不同:始终跟踪合并的所有父级,即使它与其中一个父级是 TREESAME。即使合并的一个以上侧包含的提交,这也不意味着合并本身也包含在内!在本例中,我们得到
I A B N D O P Q
M
被排除,因为它与两个父级都是 TREESAME。E
、C
和B
都被遍历了,但只有B
是 !TREESAME,所以其他的不出现。请注意,如果没有父级重写,很难真正谈论提交之间的父/子关系,因此我们将它们显示为断开连接。
- --full-history 带父重写
-
普通提交仅在它们是 !TREESAME 时才包含(尽管这可以更改,请参阅下面的
--sparse
)。合并总是被包含。然而,它们的父列表被重写:沿每个父列表,修剪掉本身未包含的提交。这导致
.-A---M---N---O---P---Q / / / / / I B / D / \ / / / / `-------------'
与上面不带重写的
--full-history
进行比较。注意E
被修剪掉了,因为它是一个 TREESAME,但是P
的父列表被重写为包含E
的父I
。同样的事情也发生在C
和N
,以及X
、Y
和Q
上。
除了上述设置之外,您还可以更改 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 \ / / `---------'
注意
N
、P
和Q
相对于--full-history
的主要区别:-
N
的父列表移除了I
,因为它是另一个父M
的祖先。尽管如此,N
仍然保留,因为它不是 TREESAME。 -
P
的父列表类似地移除了I
。P
随后被完全移除,因为它有一个父级且是 TREESAME。 -
Q
的父列表将Y
简化为X
。X
随后被移除,因为它是一个 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
引入的错误污染并且需要修复时,我们可能只想查看 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
,它被 A
、B
和 X
以不同方式修改。单父提交 C
、Z
和 Y
不修改 file.txt
。合并提交 M
是通过解决合并冲突以包含来自 A
和 B
的两个更改而创建的,因此它与任何一个都不是 TREESAME。然而,合并提交 R
是通过忽略 M
处 file.txt
的内容而仅采用 X
处 file.txt
的内容而创建的。因此,R
与 X
是 TREESAME,但与 M
不是。最后,创建 N
的自然合并解决方案是采用 R
处 file.txt
的内容,因此 N
与 R
是 TREESAME,但与 C
不是。合并提交 O
和 P
与它们的第一个父级是 TREESAME,但与它们的第二个父级 Z
和 Y
分别不是。
在使用默认模式时,N
和 R
都具有一个 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
不太可能是用于合并到重要分支的合并提交。相反,合并 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
文件。