简体中文 ▾ 主题 ▾ 最新版本 ▾ git-log 最后更新于 2.50.0

名称

git-log - 显示提交日志

概要

git log [<options>] [<revision-range>] [[--] <path>…​]

描述

显示提交日志。

列出通过遵循给定提交的 parent 链接可达的提交,但排除那些前面带有 ^ 的提交可达的提交。默认情况下,输出按倒序时间顺序给出。

你可以将其视为一个集合操作。从命令行上给出的任何提交可达的提交形成一个集合,然后从前面带有 ^ 的提交可达的提交将从该集合中减去。剩余的提交就是命令的输出结果。还可以使用各种其他选项和路径参数来进一步限制结果。

因此,以下命令

$ git log foo bar ^baz

表示“列出所有可从 foobar 到达,但不可从 baz 到达的提交”。

特殊符号“<commit1>..<commit2>”可用作“^<commit1> <commit2>”的简写。例如,以下任一形式都可以互换使用

$ git log origin..HEAD
$ git log HEAD ^origin

另一个特殊符号是“<commit1>…​<commit2>”,这对于合并很有用。产生的提交集合是两个操作数之间的对称差异。以下两个命令是等效的

$ git log A B --not $(git merge-base --all A B)
$ git log A...B

此命令接受适用于 git-rev-list[1] 命令的选项,以控制显示内容和方式,以及适用于 git-diff[1] 命令的选项,以控制如何显示每个提交引入的更改。

选项

--follow

继续列出文件重命名后的历史(仅适用于单个文件)。

--no-decorate
--decorate[=short|full|auto|no]

打印出所显示任何提交的引用名称。如果指定 short,则不打印引用名称前缀 refs/heads/refs/tags/refs/remotes/。如果指定 full,则打印完整的引用名称(包括前缀)。如果指定 auto,则如果输出到终端,引用名称将像指定 short 一样显示,否则不显示引用名称。选项 --decorate--decorate=short 的简写。如果已配置,则默认为 log.decorate 的配置值,否则默认为 auto

--decorate-refs=<pattern>
--decorate-refs-exclude=<pattern>

对于每个候选引用,如果它与提供给 --decorate-refs-exclude 的任何模式匹配,或者它不与提供给 --decorate-refs 的任何模式匹配,则不将其用于装饰。log.excludeDecoration 配置选项允许从装饰中排除引用,但显式的 --decorate-refs 模式将覆盖 log.excludeDecoration 中的匹配项。

如果没有给出这些选项或配置设置,那么如果引用匹配 HEADrefs/heads/refs/remotes/refs/stash/refs/tags/,则将它们用作装饰。

--clear-decorations

指定此选项时,它会清除所有以前的 --decorate-refs--decorate-refs-exclude 选项,并放宽默认装饰过滤器以包含所有引用。如果配置值 log.initialDecorationSet 设置为 all,则假定此选项。

--source

打印出命令行上给出的、通过它到达每个提交的引用名称。

--[no-]mailmap
--[no-]use-mailmap

使用 mailmap 文件将作者和提交者姓名及电子邮件地址映射到规范的真实姓名和电子邮件地址。参见 git-shortlog[1]

--full-diff

如果没有此标志,git log -p <path>... 会显示修改了指定路径的提交,以及关于相同指定路径的差异。有了此标志,对于修改了指定路径的提交,将显示完整的差异;这意味着“<path>…”只限制提交,而不限制这些提交的差异。

请注意,这会影响所有基于差异的输出类型,例如 --stat 等产生的输出。

--log-size

在每个提交的输出中包含一行“log size <number>”,其中 <number> 是该提交消息的字节长度。旨在通过允许工具预先分配空间来加快从 git log 输出中读取日志消息的工具的速度。

-L<start>,<end>:<file>
-L:<funcname>:<file>

跟踪由 <start>,<end> 或函数名正则表达式 <funcname><file> 中给出的行范围的演变。您不能给出任何路径规范限制符。这目前仅限于从单个修订开始的遍历,即,您只能给出零个或一个正修订参数,并且 <start><end>(或 <funcname>)必须存在于起始修订中。您可以多次指定此选项。这意味着 --patch。补丁输出可以使用 --no-patch 抑制,但其他差异格式(即 --raw--numstat--shortstat--dirstat--summary--name-only--name-status--check)目前尚未实现。

<start><end> 可以采用以下形式之一

  • 数字

    如果 <start><end> 是一个数字,它指定一个绝对行号(行从 1 开始计数)。

  • /正则表达式/

    此形式将使用与给定 POSIX 正则表达式匹配的第一行。如果 <start> 是一个正则表达式,它将从上一个 -L 范围的末尾开始搜索(如果存在),否则从文件开头开始搜索。如果 <start>^/regex/,它将从文件开头开始搜索。如果 <end> 是一个正则表达式,它将从 <start> 给定的行开始搜索。

  • +偏移量 或 -偏移量

    这仅对 <end> 有效,并将指定 <start> 给定行之前或之后的行数。

如果用 :<funcname> 替换 <start><end>,它是一个正则表达式,表示从第一个匹配 <funcname> 的函数名行到下一个函数名行的范围。:<funcname> 从上一个 -L 范围的末尾开始搜索(如果存在),否则从文件开头开始搜索。^:<funcname> 从文件开头开始搜索。函数名确定方式与 git diff 处理补丁块头(参见 gitattributes[5]Defining a custom hunk-header)的方式相同。

<revision-range>

仅显示指定修订范围内的提交。如果没有指定 <revision-range>,则默认为 HEAD(即,导致当前提交的整个历史记录)。origin..HEAD 指定了从当前提交(即 HEAD)可达的所有提交,但不包括从 origin 可达的提交。有关拼写 <revision-range> 的完整列表,请参阅 gitrevisions[7]Specifying Ranges 部分。

[--] <path>…​

只显示足以解释指定路径匹配文件是如何产生的提交。有关详细信息和其他简化模式,请参见下面的 History Simplification

当出现混淆时,路径可能需要在前面加上 --,以将其与选项或修订范围分开。

提交限制

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

使用更多选项通常会进一步限制输出(例如,--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>

限制提交输出为引用日志条目与指定模式(正则表达式)匹配的提交。当有多个 --grep-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

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

此选项还会将合并提交的默认差异格式更改为 first-parent,详细信息请参阅 --diff-merges=first-parent

--exclude-first-parent-only

在查找要排除的提交(带 ^)时,遇到合并提交时只遵循第一个父提交。这可用于查找主题分支中从其与远程分支分歧点开始的更改集,因为任意合并都可以是有效的主题分支更改。

--not

反转所有后续修订说明符的 ^ 前缀(或其缺失)的含义,直到下一个 --not。在命令行上 --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/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

假装引用日志中提及的所有对象都作为 <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=。当看到 -- 分隔符时,后续输入将被视为路径并用于限制结果。通过标准输入读取的标志(如 --not)仅对以相同方式传递的参数有效,并且不会影响任何后续命令行参数。

--cherry-mark

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

--cherry-pick

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

例如,如果您有两个分支,AB,列出其中一侧的所有提交的常用方法是使用 --left-right(参见下面 --left-right 选项描述中的示例)。但是,它会显示从另一个分支拣选(cherry-picked)的提交(例如,“b 上的第 3 个”可能是从分支 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

不遍历提交祖先链,而是从最新引用日志条目遍历到较旧条目。使用此选项时,不能指定要排除的提交(即,不能使用 ^commitcommit1..commit2commit1...commit2 符号)。

除了 onelinereference 之外(出于显而易见的原因),使用 --pretty 格式时,这将导致输出包含取自引用日志的两行额外信息。输出中的引用日志指示符可以显示为 ref@{<Nth>}(其中 <Nth> 是引用日志中的倒序时间索引)或显示为 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 中第一个存在的伪引用。仅当索引有未合并条目时有效。此选项可用于在解决三向合并冲突时显示相关提交。

--boundary

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

历史简化

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

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

<paths>

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

--simplify-by-decoration

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

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

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

默认模式

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

--show-pulls

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

--full-history

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

--dense

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

--sparse

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

--simplify-merges

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

--ancestry-path[=<commit>]

当给定一个要显示的提交范围(例如 commit1..commit2commit2 ^commit1),以及该范围内的提交 <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。

  • Dfoo 设置为“baz”。其合并 OND 中的字符串组合为“foobarbaz”;即,它与任何父级都不是 TREESAME。

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

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

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

默认模式

如果提交与任何父提交不属于 TREESAME(尽管这可以更改,请参阅下面的 --sparse),则包含该提交。如果提交是合并,并且与一个父提交属于 TREESAME,则只跟踪该父提交。(即使有多个 TREESAME 父提交,也只跟踪其中一个。)否则,跟踪所有父提交。

这会产生

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

请注意,只跟踪 TREESAME 父提交(如果可用)的规则如何完全排除了 BC 是通过 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 的父提交 ICN,以及 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 的父提交列表也类似地移除了 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 中不存在的东西”。在此示例中,结果将是所有提交,除了 AB(当然还有 D 本身)。

然而,当我们想找出 M 中哪些提交被 D 引入的错误污染并需要修复时,我们可能只想查看 D..M 中实际是 D 后代的子集,即排除 CK。这正是 --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 属于 TREESAME。最后,创建 N 的自然合并解决方案是取 R 处的 file.txt 内容,因此 NR 属于 TREESAME 但不与 C 属于 TREESAME。合并提交 OP 与它们的第一父提交属于 TREESAME,但不与它们的第二父提交 ZY 属于 TREESAME。

当使用默认模式时,NR 都有一个 TREESAME 父提交,因此这些边被遍历,而其他边被忽略。生成的历史图是

	I---X

当使用 --full-history 时,Git 会遍历每一条边。这将发现提交 AB 以及合并 M,同时也会揭示合并提交 OP。通过父提交重写,生成的图是

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

在这里,合并提交 OP 增加了额外的噪音,因为它们实际上并没有对 file.txt 贡献任何更改。它们只是合并了一个基于旧版本 file.txt 的主题。这在许多贡献者并行工作并将他们的主题分支合并到单个主干的工作流中是一个常见问题:许多不相关的合并会出现在 --full-history 结果中。

当使用 --simplify-merges 选项时,提交 OP 会从结果中消失。这是因为 OP 重写后的第二父提交可以从它们的第一父提交到达。这些边被移除,然后这些提交看起来就像与它们的父提交属于 TREESAME 的单父提交。提交 N 也发生了同样的情况,从而产生了如下历史视图

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

在此视图中,我们看到了来自 ABX 的所有重要单父提交更改。我们还看到了仔细解决的合并 M 和不太仔细解决的合并 R。这通常足以解释为什么提交 AB 在默认视图中从历史记录中“消失”了。但是,这种方法存在一些问题。

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

第二个问题是审计。当许多贡献者在同一个仓库上工作时,哪个合并提交将更改引入重要分支是很重要的。上面有问题的合并 R 不太可能是用于合并到重要分支的合并提交。相反,合并 N 用于将 RX 合并到重要分支。此提交的消息中可能包含关于更改 X 为何会覆盖来自 AB 的更改的信息。

--show-pulls

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

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

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

在这里,合并提交 RN 被包含,因为它们分别将提交 XR 拉入主分支。这些合并是提交 AB 不出现在默认历史中的原因。

--show-pulls--simplify-merges 结合使用时,图包含所有必要的信息

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

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

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

提交排序

默认情况下,提交按逆时间顺序显示。

--date-order

在显示所有子提交之前不显示任何父提交,但除此之外,按提交时间戳顺序显示提交。

--author-date-order

在显示所有子提交之前不显示任何父提交,但除此之外,按作者时间戳顺序显示提交。

--topo-order

在显示所有子提交之前不显示任何父提交,并避免将历史记录中多行的提交混合显示。

例如,在这样的提交历史中

    ---1----2----4----7
	\	       \
	 3----5----6----8---

其中数字表示提交时间戳的顺序,git rev-list 和其他带有 --date-order 的命令会按时间戳顺序显示提交:8 7 6 5 4 3 2 1。

使用 --topo-order,它们将显示 8 6 5 3 7 4 2 1(或 8 7 4 2 6 5 3 1);一些较旧的提交会显示在较新的提交之前,以避免将来自两个并行开发分支的提交混合在一起显示。

--reverse

以相反顺序输出选择要显示的提交(参见上面的提交限制部分)。不能与 --walk-reflogs 结合使用。

对象遍历

这些选项主要用于 Git 仓库的打包。

--no-walk[=(sorted|unsorted)]

只显示给定的提交,但不遍历它们的祖先。如果指定了范围,则此选项无效。如果给定了参数 unsorted,则提交将按照它们在命令行上给出的顺序显示。否则(如果给定了 sorted 或没有给定参数),提交将按提交时间的逆时间顺序显示。不能与 --graph 结合使用。

--do-walk

覆盖之前的 --no-walk 选项。

提交格式化

--pretty[=<format>]
--format=<format>

以给定格式美观地打印提交日志的内容,其中 <format> 可以是 onelineshortmediumfullfullerreferenceemailrawformat:<string>tformat:<string> 之一。当 <format> 不属于上述任何一种,并且其中包含 %placeholder 时,它等同于给定了 --pretty=tformat:<format>

有关每种格式的更多详细信息,请参阅“PRETTY FORMATS”部分。当省略 =<format> 部分时,默认值为 medium

注意:您可以在仓库配置中指定默认的美观格式(参见 git-config[1])。

--abbrev-commit

不显示完整的 40 字节十六进制提交对象名称,而是显示一个唯一标识该对象的前缀。可以使用 "--abbrev=<n>" 选项(如果显示差异输出,此选项也会对其进行修改)来指定前缀的最小长度。

这应该会使使用 80 列终端的人员更容易阅读 "--pretty=oneline"。

--no-abbrev-commit

显示完整的 40 字节十六进制提交对象名称。这会抵消 --abbrev-commit,无论是显式的还是由其他选项(例如 "--oneline")隐式指定的。它还会覆盖 log.abbrevCommit 变量。

--oneline

这是 "--pretty=oneline --abbrev-commit" 同时使用的简写形式。

--encoding=<encoding>

提交对象在其编码头中记录了用于日志消息的字符编码;此选项可用于告诉命令以用户首选的编码重新编码提交日志消息。对于非底层命令,默认值为 UTF-8。请注意,如果一个对象声称以 X 编码,并且我们正在以 X 输出,我们将按原样输出该对象;这意味着原始提交中的无效序列可能会被复制到输出中。同样,如果 iconv(3) 无法转换提交,我们将静默地按原样输出原始对象。

--expand-tabs=<n>
--expand-tabs
--no-expand-tabs

在输出日志消息之前,对其执行制表符扩展(将每个制表符替换为足够的空格,以填充到 <n> 的倍数的下一个显示列)。--expand-tabs--expand-tabs=8 的简写,而 --no-expand-tabs--expand-tabs=0 的简写,后者禁用制表符扩展。

默认情况下,在将日志消息缩进 4 个空格的美观格式(即默认的 mediumfullfuller)中,制表符会被扩展。

--notes[=<ref>]

当显示提交日志消息时,显示注释提交的注解(参见 git-notes[1])。当命令行中没有给出 --pretty--format--oneline 选项时,这是 git loggit showgit whatchanged 命令的默认行为。

默认情况下,显示的注解来自 core.notesRefnotes.displayRef 变量中列出的注解引用(或相应的环境变量覆盖)。有关更多详细信息,请参阅 git-config[1]

如果带有可选的 <ref> 参数,则使用该引用来查找要显示的注解。当引用以 refs/notes/ 开头时,它可以指定完整的引用名称;当它以 notes/ 开头时,以 refs/ 为前缀,否则以 refs/notes/ 为前缀来形成引用的完整名称。

多个 --notes 选项可以组合使用以控制显示哪些注解。示例:"--notes=foo" 将只显示来自 "refs/notes/foo" 的注解;"--notes=foo --notes" 将显示来自 "refs/notes/foo" 和默认注解引用(一个或多个)的注解。

--no-notes

不显示注解。这会通过重置显示注解的引用列表来抵消上述 --notes 选项。选项按照命令行上给出的顺序解析,因此例如 "--notes --notes=foo --no-notes --notes=bar" 将只显示来自 "refs/notes/bar" 的注解。

--show-notes-by-default

显示默认注解,除非给出了显示特定注解的选项。

--show-notes[=<ref>]
--[no-]standard-notes

这些选项已弃用。请改用上面的 --notes/--no-notes 选项。

--show-signature

通过将签名传递给 gpg --verify 并显示输出来检查已签名提交对象的有效性。

--relative-date

等同于 --date=relative

--date=<format>

仅对以人类可读格式显示的日期生效,例如使用 --pretty 时。log.date 配置变量设置了 log 命令的 --date 选项的默认值。默认情况下,日期以原始时区(提交者或作者的时区)显示。如果将 -local 附加到格式(例如 iso-local),则使用用户的本地时区。

--date=relative 显示相对于当前时间的日期,例如“2 hours ago”。-local 选项对 --date=relative 没有影响。

--date=local--date=default-local 的别名。

--date=iso(或 --date=iso8601)以类似 ISO 8601 的格式显示时间戳。与严格 ISO 8601 格式的区别在于

  • 用空格代替日期/时间分隔符 T

  • 时间与时区之间有一个空格

  • 时区的小时和分钟之间没有冒号

--date=iso-strict(或 --date=iso8601-strict)以严格的 ISO 8601 格式显示时间戳。

--date=rfc(或 --date=rfc2822)以 RFC 2822 格式显示时间戳,这种格式常见于电子邮件中。

--date=short 只显示日期,不显示时间,格式为 YYYY-MM-DD

--date=raw 将日期显示为自 epoch(1970-01-01 00:00:00 UTC)以来的秒数,后跟一个空格,然后是作为 UTC 偏移量的时区(一个带四个数字的 +-;前两位是小时,后两位是分钟)。即,如同时间戳用 strftime("%s %z") 格式化一样。请注意,-local 选项不影响自 epoch 以来的秒数值(该值始终以 UTC 衡量),但会切换随附的时区值。

--date=human 在时区与当前时区不匹配时显示时区,如果匹配则不打印整个日期(即,对于“今年”的日期跳过打印年份,但如果日期在最近几天并且我们可以直接说出是星期几,则跳过整个日期本身)。对于较旧的日期,小时和分钟也被省略。

--date=unix 将日期显示为 Unix epoch 时间戳(自 1970 年以来的秒数)。与 --raw 一样,这始终是 UTC 时间,因此 -local 没有效果。

--date=format:... 将格式 ... 传递给您的系统 strftime 函数,但 %s、%z 和 %Z 除外,它们在内部处理。使用 --date=format:%c 以您系统区域设置的首选格式显示日期。有关格式占位符的完整列表,请参阅 strftime 手册。当使用 -local 时,正确的语法是 --date=format-local:...

--date=default 是默认格式,基于 ctime(3) 输出。它显示一行,包含三字母的星期几、三字母的月份、日期、"HH:MM:SS" 格式的小时-分钟-秒,后跟四位数年份,以及时区信息,除非使用本地时区,例如 Thu Jan 1 00:00:00 1970 +0000

--parents

同时打印提交的父提交(格式为 "commit parent…​")。也启用父提交重写,参见上文的 历史简化

--children

同时打印提交的子提交(格式为 "commit child…​")。也启用父提交重写,参见上文的 历史简化

--left-right

标记提交可从对称差异的哪一侧到达。来自左侧的提交前缀为 <,来自右侧的提交前缀为 >。如果与 --boundary 结合使用,则这些提交前缀为 -

例如,如果您有此拓扑

	     y---b---b  branch B
	    / \ /
	   /   .
	  /   / \
	 o---x---a---a  branch A

您将得到如下输出

	$ git rev-list --left-right --boundary --pretty=oneline A...B

	>bbbbbbb... 3rd on b
	>bbbbbbb... 2nd on b
	<aaaaaaa... 3rd on a
	<aaaaaaa... 2nd on a
	-yyyyyyy... 1st on b
	-xxxxxxx... 1st on a
--graph

在输出的左侧绘制提交历史的基于文本的图形表示。这可能会导致在提交之间打印额外的行,以便正确绘制图形历史。不能与 --no-walk 结合使用。

这会启用父提交重写,参见上文的 历史简化

这默认隐含了 --topo-order 选项,但也可以指定 --date-order 选项。

--show-linear-break[=<barrier>]

当不使用 --graph 时,所有历史分支都会被展平,这可能导致难以看出两个连续的提交不属于同一个线性分支。在这种情况下,此选项会在它们之间放置一个分隔符。如果指定了 <barrier>,则它是将代替默认分隔符显示的字符串。

美观格式 (PRETTY FORMATS)

如果提交是合并提交,并且美观格式不是 onelineemailraw,则会在 Author: 行之前插入额外一行。此行以 "Merge: " 开头,并打印祖先提交的哈希值,用空格分隔。请注意,如果您限制了历史视图,列出的提交可能不一定是直接父提交的列表:例如,如果您只对与特定目录或文件相关的更改感兴趣。

有几种内置格式,您可以通过将 pretty.<name> 配置选项设置为另一个格式名称或 format: 字符串来定义其他格式,如下所述(参见 git-config[1])。以下是内置格式的详细信息

  • oneline

    <hash> <title-line>

    这被设计为尽可能紧凑。

  • short

    commit <hash>
    Author: <author>
    <title-line>
  • medium

    commit <hash>
    Author: <author>
    Date:   <author-date>
    <title-line>
    <full-commit-message>
  • full

    commit <hash>
    Author: <author>
    Commit: <committer>
    <title-line>
    <full-commit-message>
  • fuller

    commit <hash>
    Author:     <author>
    AuthorDate: <author-date>
    Commit:     <committer>
    CommitDate: <committer-date>
    <title-line>
    <full-commit-message>
  • reference

    <abbrev-hash> (<title-line>, <short-author-date>)

    此格式用于在提交消息中引用另一个提交,并且与 --pretty='format:%C(auto)%h (%s, %ad) 相同。默认情况下,日期使用 --date=short 格式化,除非明确指定了另一个 --date 选项。与任何带有格式占位符的 format: 一样,其输出不受 --decorate--walk-reflogs 等其他选项的影响。

  • email

    From <hash> <date>
    From: <author>
    Date: <author-date>
    Subject: [PATCH] <title-line>
    <full-commit-message>
  • mboxrd

    email 类似,但提交消息中以 "From " 开头(前面带零个或多个 ">")的行会用 ">" 引用,这样它们就不会被误认为是新提交的开始。

  • raw

    raw 格式精确地显示整个提交,正如它存储在提交对象中一样。值得注意的是,哈希值会完整显示,无论是否使用了 --abbrev 或 --no-abbrev,并且 parents 信息显示的是真实的父提交,不考虑嫁接或历史简化。请注意,此格式影响提交的显示方式,但不影响差异的显示方式,例如使用 git log --raw。要在原始差异格式中获取完整的对象名称,请使用 --no-abbrev

  • format:<format-string>

    format:<format-string> 格式允许您指定要显示的信息。它的工作方式有点像 printf 格式,但一个显著的区别是,您使用 %n 而不是 \n 来获取换行符。

    例如,format:"The author of %h was %an, %ar%nThe title was >>%s<<%n" 会显示如下内容

    The author of fe6e0ee was Junio C Hamano, 23 hours ago
    The title was >>t4119: test autocomputing -p<n> for traditional diff input.<<

    占位符有

    • 扩展为单个文字字符的占位符

      %n

      换行

      %%

      一个原始的 %

      %x00

      %x 后跟两位十六进制数字会被替换为具有该十六进制数字值的字节(在本文档的其余部分,我们将此称为“字面格式代码”)。

    • 影响后续占位符格式的占位符

      %Cred

      切换颜色为红色

      %Cgreen

      切换颜色为绿色

      %Cblue

      切换颜色为蓝色

      %Creset

      重置颜色

      %C(…​)

      颜色规范,如 git-config[1] 的“配置文件”部分的“值”下所述。默认情况下,颜色仅在为日志输出启用时(通过 color.diffcolor.ui--color,并且如果我们将输出到终端,则遵循前者的 auto 设置)才显示。 %C(auto,...) 被接受为默认值的历史同义词(例如 %C(auto,red))。指定 %C(always,...) 将即使在颜色未被启用时也显示颜色(但考虑直接使用 --color=always 来为整个输出启用颜色,包括此格式和 Git 可能着色的任何其他内容)。单独的 auto(即 %C(auto))将在下一个占位符上启用自动着色,直到颜色再次切换。

      %m

      左 (<)、右 (>) 或边界 (-) 标记

      %w([<w>[,<i1>[,<i2>]]])

      切换行回绕,类似于 git-shortlog[1] 的 -w 选项。

      %<( <N> [,trunc|ltrunc|mtrunc])

      使下一个占位符至少占据 N 列宽度,如有必要,在右侧填充空格。如果输出长于 N 列,可选地在左侧(ltrunc)使用省略号 .. 截断 ..ft,在中间(mtrunc)截断 mi..le,或在末尾(trunc)截断 rig..。注意1:截断仅在 N >= 2 时正确工作。注意2:N 和 M 值(见下文)周围的空格是可选的。注意3:表情符号和其他宽字符将占据两个显示列,这可能超出列边界。注意4:分解字符组合标记可能在填充边界处错位。

      %<|( <M> )

      使下一个占位符至少占据到第 M 个显示列,如有必要,在右侧填充空格。使用负值 M 表示从终端窗口右侧边缘测量的列位置。

      %>( <N> ), %>|( <M> )

      分别类似于 %<( <N> )%<|( <M> ),但在左侧填充空格

      %>>( <N> ), %>>|( <M> )

      分别类似于 %>( <N> )%>|( <M> ),但如果下一个占位符占用的空间多于给定空间且其左侧有空格,则使用这些空格

      %><( <N> ), %><|( <M> )

      分别类似于 %<( <N> )%<|( <M> ),但填充两侧(即文本居中)

    • 展开为从提交中提取的信息的占位符

      %H

      提交哈希

      %h

      缩写提交哈希

      %T

      树哈希

      %t

      缩写树哈希

      %P

      父哈希

      %p

      缩写父哈希

      %an

      作者姓名

      %aN

      作者姓名(遵循 .mailmap,参见 git-shortlog[1]git-blame[1]

      %ae

      作者电子邮件

      %aE

      作者电子邮件(遵循 .mailmap,参见 git-shortlog[1]git-blame[1]

      %al

      作者电子邮件本地部分(@ 符号之前的部分)

      %aL

      作者本地部分(参见 %al,遵循 .mailmap,参见 git-shortlog[1]git-blame[1]

      %ad

      作者日期(格式遵循 --date= 选项)

      %aD

      作者日期,RFC2822 风格

      %ar

      作者日期,相对时间

      %at

      作者日期,UNIX 时间戳

      %ai

      作者日期,类似 ISO 8601 格式

      %aI

      作者日期,严格 ISO 8601 格式

      %as

      作者日期,短格式 (YYYY-MM-DD)

      %ah

      作者日期,人类可读风格(如 git-rev-list[1]--date=human 选项)

      %cn

      提交者姓名

      %cN

      提交者姓名(遵循 .mailmap,参见 git-shortlog[1]git-blame[1]

      %ce

      提交者电子邮件

      %cE

      提交者电子邮件(遵循 .mailmap,参见 git-shortlog[1]git-blame[1]

      %cl

      提交者电子邮件本地部分(@ 符号之前的部分)

      %cL

      提交者本地部分(参见 %cl,遵循 .mailmap,参见 git-shortlog[1]git-blame[1]

      %cd

      提交者日期(格式遵循 --date= 选项)

      %cD

      提交者日期,RFC2822 风格

      %cr

      提交者日期,相对时间

      %ct

      提交者日期,UNIX 时间戳

      %ci

      提交者日期,类似 ISO 8601 格式

      %cI

      提交者日期,严格 ISO 8601 格式

      %cs

      提交者日期,短格式 (YYYY-MM-DD)

      %ch

      提交者日期,人类可读风格(如 git-rev-list[1]--date=human 选项)

      %d

      引用名称,类似于 git-log[1] 的 --decorate 选项

      %D

      引用名称,不带 " ("、")" 包裹。

      %(decorate[:<options>])

      带有自定义装饰的引用名称。 decorate 字符串后面可以跟一个冒号和零个或多个逗号分隔的选项。选项值可以包含字面格式代码。由于其在选项语法中的作用,必须使用这些代码来表示逗号 (%x2C) 和右括号 (%x29)。

      • prefix=<value>:在引用名称列表之前显示。默认为 " ("。

      • suffix=<value>:在引用名称列表之后显示。默认为 ")"。

      • separator=<value>:在引用名称之间显示。默认为 ", "。

      • pointer=<value>:如果 HEAD 指向某个分支,则在 HEAD 和该分支之间显示。默认为 " -> "。

      • tag=<value>:在标签名称之前显示。默认为 "tag: "。

    例如,生成不带包裹或标签注释的装饰,并使用空格作为分隔符

    + %(decorate:prefix=,suffix=,tag=,separator= )

    %(describe[:<options>])

    人类可读的名称,类似于 git-describe[1];对于不可描述的提交,为空字符串。 describe 字符串后面可以跟一个冒号和零个或多个逗号分隔的选项。当同时添加或删除标签时,描述可能不一致。

    • tags[=<bool-value>]:除了只考虑带注释的标签,也考虑轻量级标签。

    • abbrev=<number>:不使用缩写对象名称的默认十六进制数字位数(将根据仓库中的对象数量而变化,默认值为 7),而是使用 <number> 位数,或者根据需要使用足够的位数来形成唯一的对象名称。

    • match=<pattern>:只考虑匹配给定 glob(7) 模式的标签,不包括 "refs/tags/" 前缀。

    • exclude=<pattern>:不考虑匹配给定 glob(7) 模式的标签,不包括 "refs/tags/" 前缀。

    %S

    在命令行上给出的引用名称,通过它到达了提交(如 git log --source),仅适用于 git log

    %e

    编码

    %s

    主题

    %f

    净化后的主题行,适合作为文件名

    %b

    正文

    %B

    原始正文(未回绕的主题和正文)

    %N

    提交注释

    %GG

    来自 GPG 的原始验证消息,用于已签名提交

    %G?

    对于有效签名显示 "G",对于无效签名显示 "B",对于有效但未知有效性的签名显示 "U",对于已过期的有效签名显示 "X",对于由已过期密钥创建的有效签名显示 "Y",对于由已撤销密钥创建的有效签名显示 "R",如果无法检查签名(例如缺少密钥)显示 "E",如果没有签名显示 "N"

    %GS

    显示已签名提交的签名者姓名

    %GK

    显示用于签署已签名提交的密钥

    %GF

    显示用于签署已签名提交的密钥指纹

    %GP

    显示其子密钥用于签署已签名提交的主密钥指纹

    %GT

    显示用于签署已签名提交的密钥的信任级别

    %gD

    引用日志选择器,例如 refs/stash@{1}refs/stash@{2 minutes ago};格式遵循 -g 选项描述的规则。 @ 之前的部分是命令行上给出的引用名称(因此 git log -g refs/heads/master 将产生 refs/heads/master@{0})。

    %gd

    缩短的引用日志选择器;与 %gD 相同,但引用名称部分被缩短以提高人类可读性(因此 refs/heads/master 变为 master)。

    %gn

    引用日志身份名称

    %gN

    引用日志身份名称(遵循 .mailmap,参见 git-shortlog[1]git-blame[1]

    %ge

    引用日志身份电子邮件

    %gE

    引用日志身份电子邮件(遵循 .mailmap,参见 git-shortlog[1]git-blame[1]

    %gs

    引用日志主题

    %(trailers[:<options>])

    显示 git-interpret-trailers[1] 解析的正文尾注。 trailers 字符串后面可以跟一个冒号和零个或多个逗号分隔的选项。如果任何选项提供了多次,则以最后一次出现为准。

    • key=<key>:仅显示指定 <key> 的尾注。匹配不区分大小写,并且尾随冒号是可选的。如果多次给定此选项,则显示与任何键匹配的尾注行。此选项会自动启用 only 选项,以便隐藏尾注块中的非尾注行。如果不需要此行为,可以使用 only=false 禁用它。例如,%(trailers:key=Reviewed-by) 显示键为 Reviewed-by 的尾注行。

    • only[=<bool>]:选择是否包含尾注块中的非尾注行。

    • separator=<sep>:指定插入在尾注行之间的分隔符。默认为换行符。字符串 <sep> 可以包含上面描述的字面格式代码。要使用逗号作为分隔符,必须使用 %x2C,否则它将被解析为下一个选项。例如,%(trailers:key=Ticket,separator=%x2C ) 显示所有键为 "Ticket" 的尾注行,并用逗号和空格分隔。

    • unfold[=<bool>]:使其行为类似于给定 interpret-trailer 的 --unfold 选项。例如,%(trailers:only,unfold=true) 展开并显示所有尾注行。

    • keyonly[=<bool>]:仅显示尾注的键部分。

    • valueonly[=<bool>]:仅显示尾注的值部分。

    • key_value_separator=<sep>:指定插入在每个尾注的键和值之间的分隔符。默认为 ": "。否则,它与上面的 separator=<sep> 具有相同的语义。

注意
某些占位符可能取决于修订版本遍历引擎给出的其他选项。例如,除非我们正在遍历引用日志条目(例如,通过 git log -g),否则 %g* 引用日志选项将插入一个空字符串。如果命令行上尚未提供 --decorate,则 %d%D 占位符将使用“短”装饰格式。

布尔选项接受可选值 [=<bool-value>]git-config[1]--type=bool 接受的值,如 yesoff,都接受。不带 =<value> 地给出布尔选项等同于带 =true 地给出它。

如果在占位符的 % 之后添加 +(加号),则仅当占位符展开为非空字符串时,才会在展开之前立即插入一个换行符。

如果在占位符的 % 之后添加 -(减号),则仅当占位符展开为空字符串时,才会删除紧接在展开之前的所有连续换行符。

如果在占位符的 % 之后添加 ` `(空格),则仅当占位符展开为非空字符串时,才会在展开之前立即插入一个空格。

  • tformat

    tformat: 格式的工作方式与 format: 完全相同,不同之处在于它提供“终止符”语义而不是“分隔符”语义。换句话说,每个提交都会附加消息终止符字符(通常是换行符),而不是在条目之间放置分隔符。这意味着单行格式的最后一个条目将正确地以换行符终止,就像“oneline”格式一样。例如:

    $ git log -2 --pretty=format:%h 4da45bef \
      | perl -pe '$_ .= " -- NO NEWLINE\n" unless /\n/'
    4da45be
    7134973 -- NO NEWLINE
    
    $ git log -2 --pretty=tformat:%h 4da45bef \
      | perl -pe '$_ .= " -- NO NEWLINE\n" unless /\n/'
    4da45be
    7134973

    此外,任何包含 % 的无法识别的字符串都被解释为在其前面带有 tformat:。例如,以下两个是等效的:

    $ git log -2 --pretty=tformat:%h 4da45bef
    $ git log -2 --pretty=%h 4da45bef

差异格式化

默认情况下,git log 不生成任何差异输出。以下选项可用于显示每个提交所做的更改。

请注意,除非明确给出 --diff-merges 变体之一(包括短选项 -m-c--cc--dd),否则合并提交不会显示差异,即使选择了像 --patch 这样的差异格式,也不会匹配像 -S 这样的搜索选项。例外情况是使用 --first-parent 时,在这种情况下,first-parent 是合并提交的默认格式。

-p
-u
--patch

生成补丁(参见 使用 -p 生成补丁文本)。

-s
--no-patch

抑制差异机制的所有输出。对于像 git show 这样默认显示补丁的命令,它可用于抑制其输出,或在别名中取消命令行上早期选项(如 --patch--stat)的效果。

-m

以默认格式显示合并提交的差异。这类似于 --diff-merges=on,不同之处在于,除非同时给出 -p,否则 -m 不会产生任何输出。

-c

为合并提交生成组合差异输出。是 --diff-merges=combined -p 的快捷方式。

--cc

为合并提交生成紧凑组合差异输出。是 --diff-merges=dense-combined -p 的快捷方式。

--dd

对于合并提交和常规提交,生成相对于第一个父提交的差异。是 --diff-merges=first-parent -p 的快捷方式。

--remerge-diff

为合并提交生成重新合并差异输出。是 --diff-merges=remerge -p 的快捷方式。

--no-diff-merges

--diff-merges=off 的同义词。

--diff-merges=<format>

指定用于合并提交的差异格式。除非使用 --first-parent,否则默认为 `off`,在这种情况下,first-parent 是默认值。

支持以下格式:

off, none

禁用合并提交的差异输出。用于覆盖隐含值。

on, m

使合并提交的差异输出以默认格式显示。默认格式可以通过 log.diffMerges 配置变量更改,其默认值为 separate

first-parent, 1

显示相对于第一个父提交的完整差异。这与 --patch 为非合并提交生成的格式相同。

separate

显示相对于每个父提交的完整差异。为每个父提交生成单独的日志条目和差异。

combined, c

同时显示每个父提交与合并结果之间的差异,而不是一次显示一个父提交与结果之间的成对差异。此外,它只列出从所有父提交中修改过的文件。

dense-combined, cc

通过省略不重要的代码块进一步压缩 --diff-merges=combined 生成的输出,这些代码块在父提交中的内容只有两种变体,并且合并结果未经修改地选择了其中一种。

remerge, r

重新合并两个父提交的合并提交以创建临时树对象——可能包含带有冲突标记等的文件。然后显示该临时树与实际合并提交之间的差异。

使用此选项时发出的输出可能会更改,并且它与其他选项的交互也会更改(除非有明确文档说明)。

--combined-all-paths

使组合差异(用于合并提交)列出所有父提交的文件名。因此,它仅在 --diff-merges=[dense-]combined 使用时生效,并且可能仅在检测到文件名更改时有用(即在请求了重命名或复制检测时)。

-U<n>
--unified=<n>

生成包含 <n> 行上下文(而不是通常的三行)的 diff。隐含 --patch

--output=<file>

输出到特定文件而不是标准输出。

--output-indicator-new=<char>
--output-indicator-old=<char>
--output-indicator-context=<char>

指定用于指示生成补丁中新行、旧行或上下文行的字符。通常它们分别是 +- 和 ' '。

--raw

对于每个提交,使用原始差异格式显示更改摘要。参见 git-diff[1] 的“原始输出格式”部分。这与以原始格式显示日志本身不同,后者可以通过 --format=raw 实现。

--patch-with-raw

-p --raw 的同义词。

-t

在差异输出中显示树对象。

--indent-heuristic

启用启发式算法,该算法会移动差异块边界,使补丁更易于阅读。这是默认设置。

--no-indent-heuristic

禁用缩进启发式算法。

--minimal

花费额外时间以确保生成最小的差异。

--patience

使用“patience diff”算法生成差异。

--histogram

使用“histogram diff”算法生成差异。

--anchored=<text>

使用“anchored diff”算法生成差异。

此选项可以多次指定。

如果一行在源和目标中都存在,只存在一次,并且以 <text> 开头,则此算法会尝试阻止其在输出中显示为删除或添加。它内部使用“patience diff”算法。

--diff-algorithm=(patience|minimal|histogram|myers)

选择一种差异算法。变体如下:

default
myers

基本的贪婪差异算法。目前,这是默认值。

minimal

花费额外时间以确保生成最小的差异。

patience

生成补丁时使用“patience diff”算法。

histogram

此算法扩展了 patience 算法以“支持低出现率的常见元素”。

例如,如果您将 diff.algorithm 变量配置为非默认值,但希望使用默认值,则必须使用 --diff-algorithm=default 选项。

--stat[=<width>[,<name-width>[,<count>]]]

生成差异统计(diffstat)。默认情况下,文件名部分将使用尽可能多的空间,其余部分用于图形部分。最大宽度默认为终端宽度,如果未连接到终端则为 80 列,可以通过 <width> 覆盖。文件名部分的宽度可以通过在逗号后给出另一个宽度 <name-width> 或设置 diff.statNameWidth=<name-width> 来限制。图形部分的宽度可以通过使用 --stat-graph-width=<graph-width> 或设置 diff.statGraphWidth=<graph-width> 来限制。使用 --stat--stat-graph-width 会影响所有生成统计图的命令,而设置 diff.statNameWidthdiff.statGraphWidth 不会影响 git format-patch。通过给出第三个参数 <count>,您可以将输出限制为前 <count> 行,如果还有更多,则后面跟 ...

这些参数也可以通过 --stat-width=<width>--stat-name-width=<name-width>--stat-count=<count> 单独设置。

--compact-summary

在差异统计中输出扩展头信息的精简摘要,例如文件创建或删除(“new”或“gone”,可选 +l 如果是符号链接)和模式更改(添加或移除可执行位的 +x-x)。这些信息放置在文件名部分和图形部分之间。暗示 --stat

--numstat

类似于 --stat,但显示添加和删除的行数以十进制表示,并且路径名不缩写,使其更具机器友好性。对于二进制文件,输出两个 - 而不是显示 0 0

--shortstat

仅输出 --stat 格式的最后一行,其中包含修改文件的总数,以及添加和删除的行数。

-X [<param>,...]
--dirstat[=<param>,...]

输出每个子目录的相对改动量分布。 --dirstat 的行为可以通过传递逗号分隔的参数列表进行自定义。默认值由 diff.dirstat 配置变量控制(参见 git-config[1])。以下参数可用:

changes

通过计算已从源中删除或已添加到目标中的行数来计算目录统计数字。这会忽略文件内纯代码移动的数量。换句话说,文件内行的重新排列不会像其他更改那样被大量计数。这是未给出参数时的默认行为。

lines

通过执行常规的基于行的差异分析并汇总删除/添加的行数来计算目录统计数字。(对于二进制文件,而是计算 64 字节块,因为二进制文件没有自然的行概念)。这比 changes 行为更昂贵,但它会将文件内重新排列的行与其他更改一样进行计数。结果输出与您从其他 --*stat 选项获得的输出一致。

files

通过计算更改的文件数量来计算目录统计数字。在目录统计分析中,每个更改的文件都同等计数。这是计算成本最低的 --dirstat 行为,因为它根本不需要查看文件内容。

cumulative

也计算子目录中更改对父目录的影响。请注意,使用 cumulative 时,报告的百分比总和可能超过 100%。默认(非累积)行为可以通过 noncumulative 参数指定。

<limit>

一个整数参数,指定一个截止百分比(默认为 3%)。对更改贡献低于此百分比的目录不会显示在输出中。

示例:例如,以下命令将统计更改的文件,同时忽略更改文件总量少于10%的目录,并将子目录的计数累加到父目录中: --dirstat=files,10,cumulative

--cumulative

--dirstat=cumulative 的同义词。

--dirstat-by-file[=<param>,...]

--dirstat=files,<param>,... 的同义词。

--summary

输出扩展头信息的精简摘要,例如创建、重命名和模式更改。

--patch-with-stat

-p --stat 的同义词。

-z

使用NUL字符而非换行符来分隔提交。

此外,当--raw--numstat给定后,不要混淆路径名,并使用NUL字符作为输出字段终止符。

如果没有此选项,包含“不寻常”字符的路径名将按照配置变量 core.quotePath 的解释进行引用(参见 git-config[1])。

--name-only

仅显示后像树中每个已更改文件的名称。文件名通常以 UTF-8 编码。有关更多信息,请参阅 git-log[1] 手册页中关于编码的讨论。

--name-status

只显示每个更改文件的名称和状态。有关状态字母的含义,请参阅--diff-filter选项的说明。与--name-only类似,文件名通常以UTF-8编码。

--submodule[=<format>]

指定如何显示子模块的差异。当指定--submodule=short时,使用short格式。此格式仅显示范围内提交的起始和结束名称。当指定--submodule--submodule=log时,使用log格式。此格式列出范围内的提交,就像git-submodule[1]summary一样。当指定--submodule=diff时,使用diff格式。此格式显示提交范围内子模块内容的行内差异。如果未设置配置选项,则默认为diff.submoduleshort格式。

--color[=<when>]

显示彩色差异。--color(即不带=<when>时)等同于--color=always<when>可以是alwaysneverauto之一。

--no-color

关闭彩色 diff。它与 --color=never 相同。

--color-moved[=<mode>]

移动的代码行会以不同颜色显示。如果未指定选项,<mode>默认为no;如果给定不带模式的选项,则默认为zebra。模式必须是以下之一:

no

移动的行不进行高亮显示。

default

zebra 的同义词。未来可能会更改为更合理的模式。

plain

在某个位置添加又在另一个位置删除的任何行将使用color.diff.newMoved颜色显示。类似地,color.diff.oldMoved将用于差异中在其他位置添加的已删除行。此模式会捕获任何移动的行,但在审查时,若要确定代码块是否未经过置换而移动,则此模式用处不大。

blocks

至少20个字母数字字符的移动文本块会被贪婪地检测到。检测到的块将使用color.diff.(old|new)Moved颜色进行着色。相邻的块无法区分。

zebra

移动文本块的检测方式与blocks模式相同。这些块将使用color.diff.(old|new)Moved颜色或color.diff.(old|new)MovedAlternative颜色进行着色。两种颜色之间的变化表示检测到了新的块。

dimmed-zebra

zebra类似,但会对移动代码中不重要的部分进行额外变暗处理。两个相邻块的边界行被视为重要,其余则不重要。dimmed_zebra是一个已弃用的同义词。

--no-color-moved

关闭移动检测。这可以用于覆盖配置设置。它与 --color-moved=no 相同。

--color-moved-ws=<mode>,...

这配置了在执行 --color-moved 的移动检测时如何忽略空白。这些模式可以作为逗号分隔的列表给出:

no

执行移动检测时不忽略空白。

ignore-space-at-eol

忽略行尾空格的更改。

ignore-space-change

忽略空格数量的变化。这会忽略行尾的空格,并将所有其他一个或多个空格序列视为等效。

ignore-all-space

比较行时忽略空格。即使一行有空格而另一行没有,这也忽略了差异。

allow-indentation-change

在移动检测中最初忽略所有空白,然后仅当每行的空白更改相同时,才将移动的代码块分组为一个块。这与其他模式不兼容。

--no-color-moved-ws

执行移动检测时不忽略空白。这可以用于覆盖配置设置。它与 --color-moved-ws=no 相同。

--word-diff[=<mode>]

默认情况下,单词由空白分隔;参见下面的 --word-diff-regex<mode> 默认为 plain,并且必须是以下之一:

color

仅使用颜色高亮显示更改的单词。隐含 --color

plain

将单词显示为[-removed-]{added}。如果分隔符出现在输入中,它不会尝试转义,因此输出可能会有歧义。

porcelain

使用一种特殊的、面向脚本消费的基于行的格式。添加/删除/未更改的行以通常的统一差异格式打印,行首以+/-/` `字符开头,并延伸到行尾。输入中的换行符由单独一行上的波浪号~表示。

none

再次禁用单词 diff。

请注意,尽管第一个模式的名称如此,如果启用,所有模式都使用颜色高亮显示更改的部分。

--word-diff-regex=<regex>

使用 <regex> 来决定什么是单词,而不是将非空白字符的连续序列视为一个单词。除非已启用,否则这也隐含 --word-diff

<regex>的每个不重叠匹配都被视为一个单词。这些匹配之间的任何内容都被视为空白并被忽略(!)以查找差异。您可能希望在正则表达式中附加|[^[:space:]]以确保它匹配所有非空白字符。包含换行符的匹配会在换行符处被静默截断(!)

例如,--word-diff-regex=. 会将每个字符视为一个单词,并相应地逐字符显示差异。

正则表达式也可以通过差异驱动程序或配置选项设置,请参阅gitattributes[5]git-config[1]。显式指定它会覆盖任何差异驱动程序或配置设置。差异驱动程序会覆盖配置设置。

--color-words[=<regex>]

相当于 --word-diff=color 加上(如果指定了正则表达式)--word-diff-regex=<regex>

--no-renames

关闭重命名检测,即使配置文件默认开启。

--[no-]rename-empty

是否使用空 blob 作为重命名源。

--check

如果更改引入了冲突标记或空白错误,则发出警告。哪些被认为是空白错误由core.whitespace配置控制。默认情况下,行尾空白(包括仅由空白组成的行)以及行初始缩进内紧跟制表符的空格字符都被视为空白错误。如果发现问题,则以非零状态退出。与--exit-code不兼容。

--ws-error-highlight=<kind>

高亮显示差异的contextoldnew行中的空白错误。多个值用逗号分隔,none会重置先前的值,default会将列表重置为newallold,new,context的简写。如果未给定此选项且未设置配置变量diff.wsErrorHighlight,则仅高亮显示new行中的空白错误。空白错误会使用color.diff.whitespace着色。

--full-index

在生成补丁格式输出时,不在“index”行上显示前几个字符,而是显示完整的原图像和后图像 blob 对象名称。

--binary

除了 --full-index 之外,还输出一个二进制 diff,该 diff 可以用 git-apply 应用。隐含 --patch

--abbrev[=<n>]

在diff-raw格式输出和diff-tree头行中,不显示完整的40字节十六进制对象名称,而是显示最短的、至少<n>位十六进制数字的唯一标识对象的短前缀。在diff-patch输出格式中,--full-index具有更高的优先级,即如果指定了--full-index,则无论--abbrev如何,都将显示完整的blob名称。非默认的位数可以通过--abbrev=<n>指定。

-B[<n>][/<m>]
--break-rewrites[=[<n>][/<m>]]

将完整的重写更改分解为删除和创建对。这有两个目的:

它影响文件完全重写时的变更显示方式:不显示为一连串删除和插入(其中只有极少数行与上下文文本匹配),而是显示为一次性删除所有旧内容,然后一次性插入所有新内容,数字<m>控制-B选项的这一方面(默认为60%)。-B/70%指定,如果结果中保留的原始内容少于30%,Git会将其视为完全重写(即,否则生成的补丁将是一系列删除和插入与上下文行混合在一起)。

当与-M一起使用时,完全重写的文件也被视为重命名的源(通常-M只将已消失的文件视为重命名的源),数字<n>控制-B选项的这一方面(默认为50%)。-B20%指定,与文件大小的20%或更多进行增删的更改,有资格被视为重命名到另一个文件的可能来源。

-M[<n>]
--find-renames[=<n>]

如果生成差异,则为每个提交检测并报告重命名。有关遍历历史记录时跨重命名跟踪文件的信息,请参阅--follow。如果<n>是指定的,它是相似性指数的阈值(即与文件大小相比的添加/删除量)。例如,-M90%表示如果文件有90%以上未更改,Git应将删除/添加对视为重命名。不带%符号时,该数字应理解为小数,小数点位于数字之前。例如,-M5变为0.5,因此与-M50%相同。类似地,-M05-M5%相同。若要将检测限制为精确重命名,请使用-M100%。默认相似性指数为50%。

-C[<n>]
--find-copies[=<n>]

检测复制和重命名。另请参见 --find-copies-harder。如果指定了 <n>,其含义与 -M<n> 相同。

--find-copies-harder

出于性能原因,默认情况下,-C选项仅在复制的原始文件在同一变更集中被修改时才查找副本。此标志使命令检查未修改的文件作为复制源的候选文件。这对于大型项目来说是一个非常昂贵的操作,因此请谨慎使用。给定多个-C选项具有相同的效果。

-D
--irreversible-delete

删除时省略原始图像(preimage),即只打印头信息,而不打印原始图像与/dev/null之间的差异。生成的补丁不适用于patchgit apply;这仅适用于那些只想专注于审查更改后文本的人。此外,输出显然缺乏足够的信息来逆向应用此类补丁,即使是手动操作也不行,因此得名此选项。

-B 一起使用时,也会省略删除/创建对的删除部分中的原始图像。

-l<num>

-M-C选项包含一些初步步骤,可以廉价地检测重命名/复制的子集,然后是穷举回退部分,将所有剩余的未配对目标与所有相关源进行比较。(对于重命名,只有剩余的未配对源是相关的;对于复制,所有原始源都是相关的。)对于N个源和目标,这种穷举检查的时间复杂度为O(N^2)。如果涉及的源/目标文件数量超过指定值,此选项可阻止重命名/复制检测的穷举部分运行。默认为diff.renameLimit。请注意,值0被视为无限制。

--diff-filter=[(A|C|D|M|R|T|U|X|B)...[*]]

只选择那些已添加(A)、已复制(C)、已删除(D)、已修改(M)、已重命名(R)、类型(即普通文件、符号链接、子模块等)已更改(T)、未合并(U)、未知(X)或配对已损坏(B)的文件。可以使用过滤字符的任意组合(包括不使用任何字符)。当*(全选或不选)添加到组合中时,如果比较中有任何文件匹配其他条件,则选择所有路径;如果没有文件匹配其他条件,则不选择任何内容。

此外,这些大写字母可以小写以进行排除。例如,--diff-filter=ad 会排除已添加和已删除的路径。

请注意,并非所有 diff 都能包含所有类型。例如,如果禁用对这些类型的检测,则不会出现已复制和已重命名条目。

-S<string>

查找更改文件中指定 <string> 出现次数(即添加/删除)的差异。供脚本编写者使用。

当您正在寻找一个精确的代码块(如结构体)并希望了解该代码块自首次出现以来的历史记录时,它非常有用:迭代使用此功能,将原始图像中感兴趣的代码块重新输入到-S中,并持续操作直到找到该代码块的最初版本。

二进制文件也会被搜索。

-G<regex>

查找其补丁文本包含与 <regex> 匹配的添加/删除行的差异。

为了说明-S<regex> --pickaxe-regex-G<regex>之间的区别,请考虑同一个文件中包含以下差异的提交

+    return frotz(nitfol, two->ptr, 1, 0);
...
-    hit = frotz(nitfol, mf2.ptr, 1, 0);

虽然git log -G"frotz\(nitfol"会显示此提交,但git log -S"frotz\(nitfol" --pickaxe-regex不会(因为该字符串的出现次数没有变化)。

除非提供了 --text,否则没有 textconv 过滤器的二进制文件的补丁将被忽略。

有关更多信息,请参见 gitdiffcore[7] 中的 *pickaxe* 条目。

--find-object=<object-id>

查找更改指定对象出现次数的差异。类似于 -S,只是参数不同,它不搜索特定字符串,而是搜索特定对象 ID。

该对象可以是 blob 或子模块提交。它隐含了 git-log 中的 -t 选项,以也查找树。

--pickaxe-all

-S-G 找到更改时,显示该变更集中所有更改,而不仅仅是包含 <string> 更改的文件。

--pickaxe-regex

将提供给 -S<string> 视为扩展的 POSIX 正则表达式进行匹配。

-O<orderfile>

控制文件在输出中出现的顺序。这会覆盖diff.orderFile配置变量(参见git-config[1])。要取消diff.orderFile,请使用-O/dev/null

输出顺序由<orderfile>中的glob模式顺序决定。所有路径名匹配第一个模式的文件首先输出,所有路径名匹配第二个模式(但不匹配第一个)的文件其次输出,依此类推。所有路径名不匹配任何模式的文件最后输出,就像文件末尾有一个隐式匹配所有模式一样。如果多个路径名具有相同的级别(它们匹配相同的模式但没有匹配更早的模式),则它们相对于彼此的输出顺序是正常顺序。

<orderfile> 解析如下:

  • 空行被忽略,因此它们可以用作分隔符以提高可读性。

  • 以井号("#")开头的行被忽略,因此它们可以用作注释。如果模式以井号开头,请在模式开头添加反斜杠("\")。

  • 其他每行包含一个模式。

模式具有与fnmatch(3)中使用的模式相同的语法和语义,但不带FNM_PATHNAME标志,例外是如果删除最终路径名的任意数量的组件后匹配模式,则路径名也会匹配该模式。例如,模式"foo*bar"匹配"fooasdfbar"和"foo/bar/baz/asdf"但不匹配"foobarx"。

--skip-to=<file>
--rotate-to=<file>

从输出中丢弃在命名文件<file>之前的文件(即跳过到),或将其移动到输出末尾(即旋转到)。这些选项主要为git difftool命令而设计,否则可能用处不大。

-R

交换两个输入;即,显示从索引或磁盘文件到树内容的差异。

--relative[=<path>]
--no-relative

在项目子目录中运行时,可以使用此选项排除目录外的更改并显示相对于该目录的路径名。当您不在子目录中(例如在裸仓库中)时,可以通过提供<path>作为参数来指定输出相对于哪个子目录。--no-relative可用于撤销diff.relative配置选项和先前的--relative

-a
--text

将所有文件视为文本。

--ignore-cr-at-eol

进行比较时忽略行尾的回车符。

--ignore-space-at-eol

忽略行尾空格的更改。

-b
--ignore-space-change

忽略空格数量的变化。这会忽略行尾的空格,并将所有其他一个或多个空格序列视为等效。

-w
--ignore-all-space

比较行时忽略空格。即使一行有空格而另一行没有,这也忽略了差异。

--ignore-blank-lines

忽略所有空行的更改。

-I<regex>
--ignore-matching-lines=<regex>

忽略所有行都匹配 <regex> 的更改。此选项可以多次指定。

--inter-hunk-context=<number>

在差异块之间显示上下文,最多达指定行数 <number>,从而合并彼此接近的块。默认为 diff.interHunkContext,如果未设置配置选项则为 0。

-W
--function-context

为每个更改显示整个函数作为上下文行。函数名称的确定方式与git diff确定补丁块头(patch hunk headers)的方式相同(请参阅gitattributes[5]中的“定义自定义块头”)。

--ext-diff

允许执行外部差异辅助程序。如果您使用 gitattributes[5] 设置了外部差异驱动程序,则需要与 git-log[1] 等命令一起使用此选项。

--no-ext-diff

禁止外部差异驱动程序。

--textconv
--no-textconv

允许(或不允许)在比较二进制文件时运行外部文本转换过滤器。有关详细信息,请参阅gitattributes[5]。由于文本转换过滤器通常是单向转换,因此生成的差异适合人工阅读,但无法应用。因此,文本转换过滤器默认只对git-diff[1]git-log[1]启用,而不对git-format-patch[1]或diff底层命令启用。

--ignore-submodules[=(none|untracked|dirty|all)]

在生成差异时忽略对子模块的更改。all是默认值。使用none会在子模块包含未跟踪或已修改文件,或者其HEAD与超级项目中记录的提交不同时,将其视为已修改,并且可以覆盖git-config[1]gitmodules[5]ignore选项的任何设置。使用untracked时,如果子模块只包含未跟踪内容,则不将其视为脏(但仍会扫描已修改内容)。使用dirty会忽略对子模块工作树的所有更改,仅显示超级项目中所存储提交的更改(这是1.7.0之前的行为)。使用all会隐藏对子模块的所有更改。

--src-prefix=<prefix>

显示给定的源前缀 <prefix> 而不是 "a/"。

--dst-prefix=<prefix>

显示给定的目标前缀 <prefix> 而不是 "b/"。

--no-prefix

不显示任何源或目标前缀。

--default-prefix

使用默认的源和目标前缀("a/"和"b/")。这会覆盖配置变量,例如diff.noprefixdiff.srcPrefixdiff.dstPrefixdiff.mnemonicPrefix(参见git-config[1])。

--line-prefix=<prefix>

在每行输出前面添加一个额外的 <prefix>

--ita-invisible-in-index

默认情况下,通过git add -N添加的条目在git diff中显示为已存在的空文件,在git diff --cached中显示为新文件。此选项使该条目在git diff中显示为新文件,在git diff --cached中显示为不存在。此选项可以通过--ita-visible-in-index恢复。这两个选项都是实验性的,将来可能会被移除。

有关这些通用选项的更详细说明,另请参见 gitdiffcore[7]

使用 -p 生成补丁文本

使用-p选项运行git-diff[1]git-log[1]git-show[1]git-diff-index[1]git-diff-tree[1]git-diff-files[1]会生成补丁文本。您可以通过GIT_EXTERNAL_DIFFGIT_DIFF_OPTS环境变量(参见git[1])以及diff属性(参见gitattributes[5])自定义补丁文本的创建。

-p 选项生成的输出与传统的 diff 格式略有不同:

  1. 它前面是“git diff”头,看起来像这样:

    diff --git a/file1 b/file2

    除非涉及重命名/复制,否则a/b/文件名是相同的。特别是,即使是创建或删除,也不会使用/dev/null代替a/b/文件名。

    当涉及重命名/复制时,file1file2 分别显示重命名/复制的源文件名称和重命名/复制生成的文件名称。

  2. 后面跟着一个或多个扩展头行:

    old mode <mode>
    new mode <mode>
    deleted file mode <mode>
    new file mode <mode>
    copy from <path>
    copy to <path>
    rename from <path>
    rename to <path>
    similarity index <number>
    dissimilarity index <number>
    index <hash>..<hash> <mode>

    文件模式 <mode> 以 6 位八进制数字打印,包括文件类型和文件权限位。

    扩展头中的路径名不包含 a/b/ 前缀。

    相似性指数是未更改行的百分比,而相异性指数是已更改行的百分比。它是一个向下取整的整数,后面跟着一个百分号。因此,相似性指数100%的值保留给两个相同的文件,而100%的相异性意味着旧文件中没有一行进入新文件。

    索引行包括更改前后的 blob 对象名称。如果文件模式没有更改,则包含 <mode>;否则,单独的行指示旧模式和新模式。

  3. 包含“不寻常”字符的路径名将按照配置变量 core.quotePath 的解释进行引用(参见 git-config[1])。

  4. 输出中所有的file1文件指代提交前的文件,而所有的file2文件指代提交后的文件。按顺序将每个更改应用到每个文件是错误的。例如,这个补丁将交换a和b

    diff --git a/a b/b
    rename from a
    rename to b
    diff --git a/b b/a
    rename from b
    rename to a
  5. Hunk 头会提及 hunk 应用到的函数名称。有关如何根据特定语言进行调整的详细信息,请参见 gitattributes[5] 中的“定义自定义 hunk-header”。

组合 diff 格式

任何生成差异的命令都可以接受-c--cc选项,以便在显示合并时生成合并差异。这是使用git-diff[1]git-show[1]显示合并时的默认格式。另请注意,您可以为这些命令中的任何一个提供适当的--diff-merges选项,以强制生成特定格式的差异。

“组合 diff”格式如下所示:

diff --combined describe.c
index fabadb8,cc95eb0..4866510
--- a/describe.c
+++ b/describe.c
@@@ -98,20 -98,12 +98,20 @@@
	return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
  }

- static void describe(char *arg)
 -static void describe(struct commit *cmit, int last_one)
++static void describe(char *arg, int last_one)
  {
 +	unsigned char sha1[20];
 +	struct commit *cmit;
	struct commit_list *list;
	static int initialized = 0;
	struct commit_name *n;

 +	if (get_sha1(arg, sha1) < 0)
 +		usage(describe_usage);
 +	cmit = lookup_commit_reference(sha1);
 +	if (!cmit)
 +		usage(describe_usage);
 +
	if (!initialized) {
		initialized = 1;
		for_each_ref(get_name);
  1. 它前面是“git diff”头,看起来像这样(使用 -c 选项时):

    diff --combined file

    或者像这样(使用 --cc 选项时):

    diff --cc file
  2. 后面跟着一个或多个扩展头行(此示例显示了一个包含两个父级的合并):

    index <hash>,<hash>..<hash>
    mode <mode>,<mode>..<mode>
    new file mode <mode>
    deleted file mode <mode>,<mode>

    mode <mode>,<mode>..<mode>行仅在至少一个<mode>与其他模式不同时出现。包含检测到的内容移动(重命名和复制检测)信息的扩展头旨在与两个<tree-ish>的差异配合使用,并且不用于合并差异格式。

  3. 后面跟着一个两行的“源文件/目标文件”头:

    --- a/file
    +++ b/file

    类似于传统 unified diff 格式的两行头,/dev/null 用于指示已创建或已删除的文件。

    然而,如果提供了 --combined-all-paths 选项,您将得到一个 N+1 行的“源文件/目标文件”头,而不是两行的“源文件/目标文件”头,其中 N 是合并提交中父级的数量:

    --- a/file
    --- a/file
    --- a/file
    +++ b/file

    如果重命名或复制检测处于活动状态,这种扩展格式会很有用,可以让您查看不同父级中文件的原始名称。

  4. 块头格式已修改,以防止人们意外将其提供给patch -p1。合并差异格式是为审查合并提交更改而创建的,并非用于应用。此更改类似于扩展索引头中的更改

    @@@ <from-file-range> <from-file-range> <to-file-range> @@@

    组合 diff 格式的块头中有(父级数量 + 1)个 @ 字符。

与传统的统一差异格式不同,传统格式显示两个文件A和B,带有一个单列前缀,其中-表示(减号 — 出现在A中但在B中被删除),+表示(加号 — 在A中缺失但在B中添加),或者" "表示(空格 — 未更改);此格式将两个或多个文件 file1、file2 等与一个文件 X 进行比较,并显示 X 与每个 fileN 的差异。输出行前会为每个fileN添加一个列,以表示X的行与它的差异。

列N中的-字符表示该行出现在fileN中,但未出现在结果中。列N中的+字符表示该行出现在结果中,而fileN没有该行(换句话说,从该父级的角度来看,该行是添加的)。

在上述示例输出中,函数签名从两个文件都发生了更改(因此 file1 和 file2 中都有两个-被删除,加上++表示添加的一行未出现在 file1 或 file2 中)。此外,其他八行与 file1 相同,但未出现在 file2 中(因此以+为前缀)。

当由 git diff-tree -c 显示时,它会将合并提交的父节点与合并结果进行比较(即 file1..fileN 是父节点)。当由 git diff-files -c 显示时,它会将两个未解决的合并父节点与工作区文件进行比较(即 file1 是阶段 2,也称为“我们的版本”;file2 是阶段 3,也称为“他们的版本”)。

示例

git log --no-merges

显示完整的提交历史,但跳过任何合并。

git log v2.6.12.. include/scsi drivers/scsi

显示从版本 v2.6.12 开始,更改了 include/scsidrivers/scsi 子目录中任何文件的所有提交。

git log --since="2 weeks ago" -- gitk

显示过去两周内对文件 gitk 的更改。使用 -- 是为了避免与名为 gitk 的 **分支** 混淆。

git log --name-status release..test

显示在“test”分支中但尚未在“release”分支中的提交,以及每个提交修改的路径列表。

git log --follow builtin/rev-list.c

显示更改了 builtin/rev-list.c 的提交,包括在该文件被赋予当前名称之前发生的提交。

git log --branches --not --remotes=origin

显示存在于任何本地分支中但不存在于 origin 的任何远程跟踪分支中的所有提交(即你拥有而 origin 没有的)。

git log master --not --remotes=*/master

显示存在于本地 master 分支中但不存在于任何远程仓库的 master 分支中的所有提交。

git log -p -m --first-parent

显示历史记录,包括更改差异,但仅从“主分支”的角度,跳过来自已合并分支的提交,并显示由合并引入的更改的完整差异。这仅在遵循严格策略,即在保持单个集成分支时合并所有主题分支时才有意义。

git log -L /int main/',/^}/:main.c

显示文件 main.c 中函数 main() 如何随时间演变。

git log -3

将要显示的提交数量限制为 3。

讨论

Git 在某种程度上是字符编码无关的。

  • blob 对象的内容是未经解释的字节序列。核心层面没有编码转换。

  • 路径名采用 UTF-8 C 规范化形式编码。这适用于树对象、索引文件、引用名称,以及命令行参数、环境变量和配置文件(.git/config(参见 git-config[1])、gitignore[5]gitattributes[5]gitmodules[5])中的路径名。

    请注意,Git 在核心层面将路径名简单地视为非 NUL 字节序列,没有路径名编码转换(Mac 和 Windows 除外)。因此,即使在使用传统扩展 ASCII 编码的平台和文件系统上,使用非 ASCII 路径名也大多可以正常工作。但是,在此类系统上创建的仓库在基于 UTF-8 的系统(例如 Linux、Mac、Windows)上将无法正常工作,反之亦然。此外,许多基于 Git 的工具简单地假定路径名为 UTF-8,并且无法正确显示其他编码。

  • 提交日志消息通常以 UTF-8 编码,但也支持其他扩展 ASCII 编码。这包括 ISO-8859-x、CP125x 以及许多其他编码,但 *不* 包括 UTF-16/32、EBCDIC 和 CJK 多字节编码(GBK、Shift-JIS、Big5、EUC-x、CP9xx 等)。

尽管我们鼓励提交日志消息使用 UTF-8 编码,但核心 Git 和 Git Porcelain 都设计为不强制项目使用 UTF-8。如果某个项目的所有参与者觉得使用传统编码更方便,Git 并不会禁止。但是,有几点需要记住。

  1. git commitgit commit-tree 会发出警告,如果提交日志消息看起来不像有效的 UTF-8 字符串,除非您明确指出您的项目使用传统编码。表示此意的方式是在 .git/config 文件中设置 i18n.commitEncoding,如下所示

    [i18n]
    	commitEncoding = ISO-8859-1

    使用上述设置创建的提交对象会在其 encoding 头中记录 i18n.commitEncoding 的值。这有助于以后查看它们的人。缺少此头则意味着提交日志消息以 UTF-8 编码。

  2. git loggit showgit blame 等命令会查看提交对象的 encoding 头,并尝试将日志消息重新编码为 UTF-8,除非另有指定。您可以通过在 .git/config 文件中设置 i18n.logOutputEncoding 来指定所需的输出编码,如下所示

    [i18n]
    	logOutputEncoding = ISO-8859-1

    如果您没有此配置变量,则会使用 i18n.commitEncoding 的值。

请注意,我们故意选择在提交时不对提交日志消息进行重新编码以强制在提交对象级别使用 UTF-8,因为重新编码为 UTF-8 不一定是可逆操作。

配置

有关核心变量,请参阅 git-config[1];有关差异生成设置,请参阅 git-diff[1]

format.pretty

--format 选项的默认值。(参见上文的 Pretty Formats)。默认为 medium

i18n.logOutputEncoding

显示日志时使用的编码。(参见上文的 Discussion)。如果设置了 i18n.commitEncoding,则默认为其值;否则为 UTF-8。

本节中此行以上的所有内容均未包含在 git-config[1] 文档中。以下内容与该文档中的内容相同

log.abbrevCommit

如果为 true,则使 git-log[1]git-show[1]git-whatchanged[1] 假定使用 --abbrev-commit 选项。您可以使用 --no-abbrev-commit 选项覆盖此设置。

log.date

设置 log 命令的默认日期时间模式。为 log.date 设置值类似于使用 git log--date 选项。详见 git-log[1]

如果格式设置为 "auto:foo" 且正在使用分页器,则日期格式将使用 "foo" 格式。否则,将使用 "default"。

log.decorate

打印出 log 命令显示的任何提交的引用名称。如果指定了 short,则不会打印引用名称前缀 refs/heads/refs/tags/refs/remotes/。如果指定了 full,则会打印完整的引用名称(包括前缀)。如果指定了 auto,那么如果输出到终端,引用名称将以 short 模式显示,否则不显示引用名称。这与 git log 命令的 --decorate 选项相同。

log.initialDecorationSet

默认情况下,git log 仅显示某些已知引用命名空间的装饰。如果指定了 all,则显示所有引用作为装饰。

log.excludeDecoration

从日志装饰中排除指定的模式。这类似于 --decorate-refs-exclude 命令行选项,但此配置选项可被 --decorate-refs 选项覆盖。

log.diffMerges

设置当指定 --diff-merges=on 时使用的差异格式,详见 git-log[1] 中的 --diff-merges 选项。默认为 separate

log.follow

如果为 true,则当给定单个 <path> 时,git log 将表现得如同使用了 --follow 选项。这与 --follow 具有相同的限制,即它不能用于跟踪多个文件,并且在非线性历史记录上效果不佳。

log.graphColors

一个以逗号分隔的颜色列表,可用于在 git log --graph 中绘制历史线条。

log.showRoot

如果为 true,则初始提交将显示为一个大型创建事件。这相当于与一个空树进行差异比较。像 git-log[1]git-whatchanged[1] 这样通常会隐藏根提交的工具现在将显示它。默认为 true。

log.showSignature

如果为 true,则使 git-log[1]git-show[1]git-whatchanged[1] 假定使用 --show-signature 选项。

log.mailmap

如果为 true,则使 git-log[1]git-show[1]git-whatchanged[1] 假定使用 --use-mailmap 选项,否则假定使用 --no-use-mailmap 选项。默认为 true。

notes.mergeStrategy

解决备注冲突时默认选择的合并策略。必须是 manualourstheirsunioncat_sort_uniq 之一。默认为 manual。有关每种策略的更多信息,请参阅 git-notes[1] 的“NOTES MERGE STRATEGIES”部分。

此设置可以通过向 git-notes[1] 传递 --strategy 选项来覆盖。

notes.<name>.mergeStrategy

将备注合并到 refs/notes/<name> 时选择的合并策略。这会覆盖更通用的 notes.mergeStrategy 设置。有关可用策略的更多信息,请参阅 git-notes[1] 的“NOTES MERGE STRATEGIES”部分。

notes.displayRef

在显示提交消息时,除了由 core.notesRefGIT_NOTES_REF 设置的默认引用外,还从哪个引用(或多个引用,如果是 glob 模式或多次指定)读取备注,在使用 git log 系列命令时。

此设置可以通过 GIT_NOTES_DISPLAY_REF 环境变量覆盖,该变量必须是一个以冒号分隔的引用或 glob 列表。

对于不存在的引用将发出警告,但与任何引用不匹配的 glob 将被静默忽略。

此设置可通过 git-log[1] 系列命令的 --no-notes 选项禁用,或通过这些命令接受的 --notes=<ref> 选项禁用。

core.notesRef 的有效值(可能被 GIT_NOTES_REF 覆盖)也会隐式添加到要显示的引用列表中。

notes.rewrite.<command>

当使用 <command>(当前为 amendrebase)重写提交时,如果此变量为 false,git 将不会从原始提交复制备注到重写后的提交。默认为 true。另请参阅下面的 notes.rewriteRef

此设置可以通过 GIT_NOTES_REWRITE_REF 环境变量覆盖,该变量必须是一个以冒号分隔的引用或 glob 列表。

notes.rewriteMode

在重写期间复制备注时(参见 notes.rewrite.<command> 选项),确定如果目标提交已有备注时该怎么做。必须是 overwriteconcatenatecat_sort_uniqignore 之一。默认为 concatenate

此设置可以通过 GIT_NOTES_REWRITE_MODE 环境变量覆盖。

notes.rewriteRef

在重写期间复制备注时,指定(完全限定的)要复制备注的引用。可以是一个 glob,在这种情况下,所有匹配引用中的备注都将被复制。您也可以多次指定此配置。

没有默认值;您必须配置此变量才能启用备注重写。将其设置为 refs/notes/commits 以启用默认提交备注的重写。

可以通过 GIT_NOTES_REWRITE_REF 环境变量覆盖。有关其格式的进一步描述,请参见上面的 notes.rewrite.<command>

GIT

Git[1] 套件的一部分

scroll-to-top