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

名称

git-format-patch - 准备用于电子邮件提交的补丁

概要

git format-patch [-k] [(-o|--output-directory) <dir> | --stdout]
		   [--no-thread | --thread[=<style>]]
		   [(--attach|--inline)[=<boundary>] | --no-attach]
		   [-s | --signoff]
		   [--signature=<signature> | --no-signature]
		   [--signature-file=<file>]
		   [-n | --numbered | -N | --no-numbered]
		   [--start-number <n>] [--numbered-files]
		   [--in-reply-to=<message-id>] [--suffix=.<sfx>]
		   [--ignore-if-in-upstream] [--always]
		   [--cover-from-description=<mode>]
		   [--rfc[=<rfc>]] [--subject-prefix=<subject-prefix>]
		   [(--reroll-count|-v) <n>]
		   [--to=<email>] [--cc=<email>]
		   [--[no-]cover-letter] [--quiet]
		   [--[no-]encode-email-headers]
		   [--no-notes | --notes[=<ref>]]
		   [--interdiff=<previous>]
		   [--range-diff=<previous> [--creation-factor=<percent>]]
		   [--filename-max-length=<n>]
		   [--progress]
		   [<common-diff-options>]
		   [ <since> | <revision-range> ]

描述

为每个非合并提交准备一个“补丁”,每个提交一个“消息”,格式类似于 UNIX 邮箱。此命令的输出方便电子邮件提交或与 git am 一起使用。

该命令生成的“消息”包含三个部分

  • 一个简短的元数据头,以 From <commit> 开头,并带有固定的 Mon Sep 17 00:00:00 2001 日期戳,以帮助“file(1)”等程序识别文件是此命令的输出,字段记录作者身份、作者日期和更改的标题(取自提交日志消息的第一段)。

  • 提交日志消息的第二段及后续段落。

  • “补丁”,即“diff -p --stat”的输出(参见 git-diff[1]),介于提交及其父项之间。

日志消息和补丁之间用一条三短横线分隔。

有两种方法可以指定要操作的提交。

  1. 单个提交 <since> 指定要输出的当前分支尖端之前的提交,这些提交不在导致 <since> 的历史中。

  2. 通用的 <revision-range> 表达式(参见 gitrevisions[7] 中的“指定修订”部分)表示指定范围内的提交。

在单个 <commit> 的情况下,第一条规则优先。要应用第二条规则,即格式化自历史开始到 <commit> 之间的所有内容,请使用 --root 选项:git format-patch --root <commit>。如果要只格式化 <commit> 本身,可以使用 git format-patch -1 <commit>

默认情况下,每个输出文件按顺序编号,从 1 开始,并使用提交消息的第一行(为避免路径名问题而进行了处理)作为文件名。使用 --numbered-files 选项时,输出文件名将仅为数字,而不附加提交的第一行。除非指定了 --stdout 选项,否则输出文件的名称将打印到标准输出。

如果指定了 -o,则输出文件将在 <dir> 中创建。否则,它们将在当前工作目录中创建。默认路径可以通过 format.outputDirectory 配置选项设置。 -o 选项优先于 format.outputDirectory。要将补丁存储在当前工作目录中,即使 format.outputDirectory 指向其他地方,请使用 -o .。所有目录组件都将被创建。

默认情况下,单个补丁的主题是“[PATCH] ”,后跟提交消息中直到第一个空行(参见 git-commit[1] 的“讨论”部分)的行串接。

输出多个补丁时,主题前缀将是“[PATCH n/m] ”。要强制为单个补丁添加 1/1,请使用 -n。要省略主题中的补丁编号,请使用 -N

如果提供了 --threadgit-format-patch 将生成 In-Reply-ToReferences 头,使第二个及后续补丁邮件 appear as replies to the first mail;这还会生成一个 Message-ID 头以供引用。

选项

-p
--no-stat

生成纯补丁,不带任何 diffstats。

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

生成带有 <n> 行上下文的 diffs,而不是通常的三行。

--output=<file>

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

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

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

--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 会影响所有生成 stat graph 的命令,而设置 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)在 diffstat 中。该信息位于文件名部分和图形部分之间。隐含 --stat

--numstat

类似于 --stat,但以十进制显示添加和删除的行数,并省略路径名缩写,以便更易于机器处理。对于二进制文件,输出两个 - 而不是说 0 0

--shortstat

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

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

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

changes

通过计算源文件中删除的行数或目标文件中添加的行数来计算 dirstat 数字。这会忽略纯代码移动 within a file 的量。换句话说,重新排列文件中的行不如其他更改计数多。这是未提供任何参数时的默认行为。

lines

通过进行常规的基于行的 diff 分析,并对删除/添加的行数进行求和来计算 dirstat 数字。(对于二进制文件,则计算 64 字节块,因为二进制文件没有自然的行概念)。这是比 changes 行为更耗时的 --dirstat 行为,但它会像其他更改一样计算文件中重新排列的行。生成的输出与其他 --*stat 选项的输出一致。

files

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

cumulative

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

<limit>

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

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

--cumulative

--dirstat=cumulative 的同义词。

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

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

--summary

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

--no-renames

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

--rename-empty
--no-rename-empty

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

--full-index

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

--binary

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

--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>]]

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

它影响了将文件完全重写(rewrite)的更改的处理方式,而不是将其视为一系列删除和插入,其中只有少量文本碰巧与上下文匹配。它将其视为一次性的全部删除后一次性的全部插入,并且数字<m>控制 -B 选项的这一方面(默认为 60%)。-B/70% 指定,如果结果中保留的原始部分少于 30%,Git 将认为这是一次完全重写(即,否则生成的 patch 将是一系列删除和插入,并带有上下文行)。

当与 -M 一起使用时,完全重写的文件也被视为重命名(rename)的源头(通常 -M 只将消失的文件视为重命名的源头),数字 <n> 控制 -B 选项的这一方面(默认为 50%)。-B20% 指定与文件大小相比,增加和删除变化达到 20% 或以上的更改有资格被选作重命名到另一个文件的可能源头。

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

检测重命名。如果指定了 <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 选项仅在复制的原始文件在同一更改集(changeset)中被修改时才查找复制。此标志使命令检查未修改的文件作为复制源的候选。对于大型项目,这是一项非常耗时的操作,因此请谨慎使用。给出多个 -C 选项具有相同的效果。

-D
--irreversible-delete

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

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

-l<num>

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

-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> 之前的(即 *skip to*)文件,或将它们移至输出末尾(即 *rotate to*)。这些选项主要用于 git difftool 命令,可能在其他情况下不太有用。

--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 生成补丁块标头的方式相同(参见 gitattributes[5] 中“定义自定义块标头”)。

--ext-diff

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

--no-ext-diff

禁止外部差异驱动程序。

--textconv
--no-textconv

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

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

在生成 diff 时忽略对子模块的更改。all 是默认值。使用 none 时,如果子模块包含未跟踪或已修改的文件,或者其 HEAD 与超级项目中记录的提交不同,则认为子模块已修改,可用于覆盖 git-config[1]gitmodules[5]ignore 选项的任何设置。使用 untracked 时,子模块仅包含未跟踪内容时不会被视为 dirty(但仍会扫描已修改内容)。使用 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 恢复。这两个选项都是实验性的,未来可能会被删除。

--max-depth=<depth>

对于命令行上给出的每个路径说明符,最多向下递归 <depth> 层目录。值为 -1 表示无限制。不能与路径说明符中的通配符组合使用。给定一个包含 foo/bar/baz 的树,以下列表显示了每个选项集生成的匹配项

  • --max-depth=0 -- foo: foo

  • --max-depth=1 -- foo: foo/bar

  • --max-depth=1 -- foo/bar: foo/bar/baz

  • --max-depth=1 -- foo foo/bar: foo/bar/baz

  • --max-depth=2 -- foo: foo/bar/baz

如果没有给出路径说明符,则深度测量方式就好像所有顶级条目都被指定一样。请注意,这与从根开始测量不同,因为 --max-depth=0 仍将返回 foo。这允许您在要求顶级条目子集的同时仍然限制深度。

请注意,此选项仅支持树对象之间的差异,不支持与索引或工作树的差异。

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

-<n>

准备来自最顶层的 <n> 个提交的补丁。

-o <dir>
--output-directory <dir>

使用 <dir> 来存储结果文件,而不是当前工作目录。

-n
--numbered

即使只有一个补丁,也以 [PATCH n/m] 格式命名输出。

-N
--no-numbered

[PATCH] 格式命名输出。

--start-number <n>

将补丁编号从 <n> 开始,而不是从 1 开始。

--numbered-files

输出文件名将是一个简单的数字序列,不附加默认的提交第一行。

-k
--keep-subject

不要从提交日志消息的第一行剥离/添加 [PATCH]

-s
--signoff

在提交消息中添加一个 Signed-off-by 尾部,使用你自己的提交者身份。有关更多信息,请参见 git-commit[1] 中的 signoff 选项。

--stdout

将所有提交以 mbox 格式打印到标准输出,而不是为每个提交创建一个文件。

--attach[=<boundary>]

创建 multipart/mixed 附件,其中第一部分是提交消息本身,第二部分是补丁本身,带有 Content-Disposition: attachment

--no-attach

禁用附件创建,覆盖配置设置。

--inline[=<boundary>]

创建 multipart/mixed 附件,其中第一部分是提交消息本身,第二部分是补丁本身,带有 Content-Disposition: inline

--thread[=<style>]
--no-thread

控制是否添加 In-Reply-ToReferences 头,以使第二个及后续邮件 appear as replies to the first。也控制生成用于引用的 Message-ID 头。

可选的 <style> 参数可以是 shallowdeepshallow 线程将每封邮件设为对系列头部的回复,头部从封面信、--in-reply-to 和第一封补丁邮件中选择,顺序如上。deep 线程将每封邮件设为对前一封邮件的回复。

默认是 --no-thread,除非设置了 format.thread 配置。不带参数的 --thread 等同于 --thread=shallow

请注意,git send-email 的默认行为是自行处理邮件线程。如果你希望 git format-patch 来处理线程,你需要确保 git send-email 的线程被禁用。

--in-reply-to=<message-id>

使第一封邮件(或所有邮件,使用 --no-thread)appear as a reply to the given <message-id>,这避免了为了提供新的补丁系列而中断线程。

--ignore-if-in-upstream

不包含与 <until>..<since> 中的提交匹配的补丁。这将检查从 <since> 可达但从 <until> 不可达的所有补丁,并将它们与正在生成的补丁进行比较,任何匹配的补丁都将被忽略。

--always

包含未引入任何更改的提交的补丁,这些补丁默认会被省略。

--cover-from-description=<mode>

控制封面信的哪些部分将使用分支的描述自动填充。

如果 <mode>messagedefault,封面信的主题将填充占位符文本。封面信的正文将填充分支的描述。这是未指定任何配置或命令行选项时的默认模式。

如果 <mode>subject,分支描述的第一段将填充封面信的主题。描述的其余部分将填充封面信的正文。

如果 <mode>auto,如果分支描述的第一段大于 100 字节,则模式将是 message,否则将使用 subject

如果 <mode>none,封面信的主题和正文都将填充占位符文本。

--description-file=<file>

使用 <file> 的内容代替分支的描述来生成封面信。

--subject-prefix=<subject-prefix>

在主题行中,使用 [<subject-prefix>] 代替标准的 [PATCH] 前缀。这可以用来命名一个补丁系列,并且可以与 --numbered 选项结合使用。

配置变量 format.subjectPrefix 也可用于为给定存储库的所有补丁配置主题前缀。这在处理来自多个存储库的补丁的邮件列表上非常有用,并且可以用来区分补丁(例如,使用“PATCH my-project”的值)。

--filename-max-length=<n>

而不是标准的 64 字节,将生成的输出文件名截断到大约 <n> 字节(过短的值将被静默地提高到合理长度)。默认为 format.filenameMaxLength 配置变量的值,或在未配置时为 64。

--rfc[=<rfc>]

将字符串 <rfc>(默认为“RFC”)添加到主题前缀。由于主题前缀默认为“PATCH”,所以默认情况下您会得到“RFC PATCH”。

RFC 意为“Request For Comments”(征求意见);在发送实验性补丁以供讨论而不是应用时使用。“--rfc=WIP”也可能是一种指示补丁尚未完成的有用方式(“WIP”代表“Work In Progress”)。

如果接收社区对于特定额外字符串的约定是将它放在主题前缀之后,那么字符串 <rfc> 可以加上一个连字符(“-”)来表示 <rfc> 的其余部分应该被追加到主题前缀后面,例如,--rfc='-(WIP) 会生成“PATCH (WIP)”。

-v <n>
--reroll-count=<n>

将系列标记为该主题的第 <n> 次迭代。输出文件名会带有 v<n> 前缀,并且主题前缀(默认为“PATCH”,但可以通过 --subject-prefix 选项配置)会附加 ` v<n>`。例如,--reroll-count=4 可能会生成 v4-0001-add-makefile.patch 文件,其中包含“Subject: [PATCH v4 1/20] Add makefile”。<n> 不必是整数(例如,允许使用“--reroll-count=4.4”或“--reroll-count=4rev2”),但使用这样的 reroll-count 的缺点是,与前一个版本的 range-diff/interdiff 不会准确说明新迭代与哪个版本进行了比较。

--to=<email>

在电子邮件头中添加 To: 头。这会添加到任何配置的头中,并且可以多次使用。否定形式 --no-to 会丢弃迄今为止添加的所有 To: 头(来自配置或命令行)。

--cc=<email>

在电子邮件头中添加 Cc: 头。这会添加到任何配置的头中,并且可以多次使用。否定形式 --no-cc 会丢弃迄今为止添加的所有 Cc: 头(来自配置或命令行)。

--from
--from=<ident>

在每个提交邮件的 From: 头中使用 ident。如果提交的作者 ident 与提供的 ident 在文本上不完全相同,则在消息正文中放置一个 From: 头,其中包含原始作者。如果没有提供 ident,则使用提交者 ident。

请注意,此选项仅在您实际发送电子邮件并希望将自己标识为发件人,但保留原始作者时才有用(并且 git am 会正确地拾取正文中的头)。另请注意,git send-email 已经为您处理了此转换,如果您将结果馈送到 git send-email,则不应使用此选项。

--force-in-body-from
--no-force-in-body-from

当通过 --from 选项指定电子邮件发件人时,默认情况下,如果发件人与作者不同,会在提交日志消息的顶部添加一个内嵌的 "From:" 来识别提交的真实作者。使用此选项,即使发件人和作者具有相同的姓名和地址,也会添加内嵌的 "From:",这在邮件列表软件篡改发件人身份时可能有所帮助。默认值为 format.forceInBodyFrom 配置变量的值。

--add-header=<header>

向电子邮件头添加任意头。这会附加到任何已配置的头之外,并且可以多次使用。例如,--add-header="Organization: git-foo"。否定形式 --no-add-header 会丢弃目前为止从配置或命令行添加的所有To:Cc: 和自定义)头。

--cover-letter
--no-cover-letter

除了补丁之外,还会生成一个封面信文件,其中包含分支描述、简短日志和整体 diffstat。在发送之前,您可以在文件中填写描述。

--encode-email-headers
--no-encode-email-headers

使用“Q编码”(RFC 2047 中描述)来编码包含非 ASCII 字符的电子邮件头,而不是按原样输出头。默认值为 format.encodeEmailHeaders 配置变量的值。

--interdiff=<previous>

为了方便审阅者,将一个 interdiff 插入到封面信中,或者作为单个补丁(1-patch series)的注释,显示补丁系列的前一个版本与当前正在格式化的系列之间的差异。previous 是一个命名先前系列顶端的单个修订版本,该系列与正在格式化的系列共享一个共同的基础(例如 git format-patch --cover-letter --interdiff=feature/v1 -3 feature/v2)。

--range-diff=<previous>

为了方便审阅者,将一个 range-diff(参见 git-range-diff[1])插入到封面信中,或者作为单个补丁(1-patch series)的注释,显示补丁系列的前一个版本与当前正在格式化的系列之间的差异。previous 可以是命名先前系列顶端的单个修订版本,如果它与正在格式化的系列共享一个共同的基础(例如 git format-patch --cover-letter --range-diff=feature/v1 -3 feature/v2),或者当系列的两个版本不重叠时,可以是修订范围(例如 git format-patch --cover-letter --range-diff=feature/v1~3..feature/v1 -3 feature/v2)。

请注意,传递给命令的 diff 选项会影响 format-patch 的主要产品的生成方式,并且它们不会传递给用于生成封面信材料的底层 range-diff 机制(这将来可能会改变)。

--creation-factor=<percent>

--range-diff 一起使用,通过调整创建/删除成本的调整因子来微调用于匹配上一个和当前补丁系列之间提交的启发式算法。有关详细信息,请参阅 git-range-diff[1]

默认值为 999(git-range-diff[1] 使用 60),因为用例是显示与同一主题的较早迭代的比较,并且工具应该在两组补丁之间找到更多的对应关系。

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

在三短线之后附加提交的 notes(参见 git-notes[1])。

这通常用于编写不属于提交日志消息本身的对提交的解释性说明,并将其包含在补丁提交中。虽然你可以在 format-patch 运行之后但在发送之前简单地编写这些解释,但将它们保留为 Git notes 可以让它们在补丁系列的多个版本之间得到维护(但请参阅 git-notes[1] 中关于 notes.rewrite 配置选项的讨论以使用此工作流程)。

除非设置了 format.notes 配置,否则默认值为 --no-notes

--signature=<signature>
--no-signature

为每条生成的邮件添加签名。根据 RFC 3676,签名与正文之间用一条 "-- " 线分隔。如果省略 signature 选项,则签名默认为 Git 版本号。

--signature-file=<file>

作用与 --signature 类似,只是签名是从文件中读取的。

--suffix=.<sfx>

生成的文件名后缀使用指定的后缀,而不是使用 .patch。一个常见的替代方法是 --suffix=.txt。留空将删除 .patch 后缀。

请注意,前导字符不一定是点;例如,你可以使用 --suffix=-patch 来得到 0001-description-of-my-change-patch

-q
--quiet

不在标准输出中打印生成的文件名。

--no-binary

不输出二进制文件的更改内容,而是显示一条通知表明这些文件已更改。使用此选项生成的补丁无法正确应用,但对于代码审查仍然有用。

--zero-commit

在每个补丁的 From 头中输出一个全零哈希,而不是提交的哈希。

--no-base
--base[=<commit>]

记录基础树信息,以标识补丁系列适用的状态。有关详细信息,请参阅下文的 BASE TREE INFORMATION 部分。如果 <commit> 是 "auto",则会自动选择一个基础提交。 --no-base 选项会覆盖 format.useAutoBase 配置。

--root

将修订参数视为 <revision-range>,即使它只是一个单独的提交(通常会被视为 <since>)。请注意,指定范围内的根提交始终被格式化为创建补丁,与此标志无关。

--progress

在生成补丁时在 stderr 上显示进度报告。

配置

您可以指定要添加到每条消息的额外邮件头行,设置主题前缀和文件后缀的默认值,在输出多个补丁时编号,添加 "To:" 或 "Cc:" 头,配置附件,更改补丁输出目录,并使用配置变量为补丁签名。

[format]
	headers = "Organization: git-foo\n"
	subjectPrefix = CHANGE
	suffix = .txt
	numbered = auto
	to = <email>
	cc = <email>
	attach [ = mime-boundary-string ]
	signOff = true
	outputDirectory = <directory>
	coverLetter = auto
	coverFromDescription = auto

讨论

git format-patch 生成的补丁采用 UNIX 邮箱格式,并带有一个固定的“magic”时间戳,以指示文件是 format-patch 的输出而不是真实的邮箱,如下所示:

From 8f72bad1baf19a53459661343e21d6491c3908d3 Mon Sep 17 00:00:00 2001
From: Tony Luck <tony.luck@intel.com>
Date: Tue, 13 Jul 2010 11:42:54 -0700
Subject: [PATCH] =?UTF-8?q?[IA64]=20Put=20ia64=20config=20files=20on=20the=20?=
 =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20diet?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

arch/arm config files were slimmed down using a python script
(See commit c2330e286f68f1c408b4aa6515ba49d57f05beae comment)

Do the same for ia64 so we can have sleek & trim looking
...

通常,它会被放在 MUA 的草稿文件夹中,编辑后在三短线之后添加不应放入更改日志的及时评论,然后作为一封邮件发送,在本例中,邮件正文以“arch/arm config files were…”开头。在接收端,读者可以将有趣的补丁保存在 UNIX 邮箱中,并使用 git-am[1] 应用它们。

当补丁是持续讨论的一部分时,git format-patch 生成的补丁可以被调整以利用 git am --scissors 功能。在对讨论的响应之后,出现一行仅由“-- >8 --”(剪刀和穿孔)组成,接着是删除了不必要头字段的补丁。

...
> So we should do such-and-such.

Makes sense to me.  How about this patch?

-- >8 --
Subject: [IA64] Put ia64 config files on the Uwe Kleine-König diet

arch/arm config files were slimmed down using a python script
...

以这种方式发送补丁时,您通常是发送自己的补丁,因此除了“From $SHA1 $magic_timestamp”标记之外,您应该从补丁文件中省略 From:Date: 行。补丁标题可能与响应的讨论主题不同,因此您很可能希望保留 Subject: 行,如上例所示。

检查补丁损坏

许多邮件程序如果设置不当会损坏空格。以下是两种常见的损坏类型:

  • 不包含任何空格的空上下文行。

  • 包含一个额外前导空格的非空上下文行。

一种测试您的 MUA 设置是否正确的测试方法是:

  • 将补丁发送给自己,方式与您通常发送的方式完全相同,但 To: 和 Cc: 行不包含列表和维护者地址。

  • 将该补丁保存为 UNIX 邮箱格式的文件。假设其名为 a.patch。

  • 应用它

    $ git fetch <project> master:test-apply
    $ git switch test-apply
    $ git restore --source=HEAD --staged --worktree :/
    $ git am a.patch

如果它无法正确应用,原因可能有多种。

  • 补丁本身无法干净地应用。这是糟糕的,但与您的 MUA 没有太大关系。在这种情况下,您可能希望先使用 git-rebase[1] 重新设置补丁,然后再重新生成它。

  • MUA 损坏了您的补丁;"am" 会抱怨补丁无法应用。查看 .git/rebase-apply/ 子目录,看看补丁文件包含什么,并检查上面提到的常见损坏模式。

  • 同时,也请检查infofinal-commit 文件。如果final-commit 中的内容不是您想在提交日志消息中看到的确切内容,那么接收者在应用您的补丁时很有可能需要手动编辑日志消息。诸如“Hi, this is my first patch.\n”之类的文字应该放在表示提交消息结束的三短线之后。

MUA 特定提示

以下是一些有关如何使用各种邮件程序成功以内联方式提交补丁的提示。

GMail

GMail 的 Web 界面没有办法关闭行换行,因此它会破坏您发送的任何电子邮件。但是,您可以使用“git send-email”通过 GMail SMTP 服务器发送补丁,或者使用任何 IMAP 电子邮件客户端连接到 Google IMAP 服务器并通过该服务器转发电子邮件。

有关使用git send-email通过 GMail SMTP 服务器发送补丁的提示,请参阅 git-send-email[1] 的 EXAMPLE 部分。

有关使用 IMAP 接口提交的提示,请参阅 git-imap-send[1] 的 EXAMPLE 部分。

Thunderbird

默认情况下,Thunderbird 会包装电子邮件并将其标记为format=flowed,这两者都会导致生成的电子邮件无法被 Git 使用。

有三种不同的方法:使用插件关闭行换行,配置 Thunderbird 不篡改补丁,或使用外部编辑器防止 Thunderbird 篡改补丁。

方法 1(插件)

安装 Toggle Line Wrap 插件,该插件可在 https://addons.thunderbird.net/thunderbird/addon/toggle-line-wrap 上找到。它在撰写器工具栏中添加了一个“Line Wrap”按钮,您可以取消选中它。现在您可以像平常一样撰写邮件(剪切+粘贴,git format-patch | git imap-send 等),但您必须手动在输入的任何文本中插入换行符。

作为额外的功能,该插件可以检测撰写器中的补丁文本,并在尚未关闭行换行时发出警告。

该插件需要对高级配置(about:config)进行一些调整。这些在下载页面上列出。

方法 2(配置)

三个步骤:

  1. 将您的邮件服务器组合配置为纯文本:编辑…账户设置…组合 & 寻址,取消选中“组合 HTML 邮件”。

  2. 将您的常规组合窗口配置为不换行。

    在 Thunderbird 2 中:编辑..首选项..组合,将纯文本消息换行设置为 0。

    在 Thunderbird 3 中:编辑..首选项..高级..配置编辑器。搜索“mail.wrap_long_lines”。切换它以确保其设置为 false。另外,搜索“mailnews.wraplength”并将值设置为 0。

  3. 禁用 format=flowed 的使用:编辑..首选项..高级..配置编辑器。搜索“mailnews.send_plaintext_flowed”。切换它以确保其设置为 false

完成之后,您应该能够像平常一样组合电子邮件(剪切+粘贴,git format-patch | git imap-send 等),并且补丁不会被破坏。

方法 3(外部编辑器)

需要以下 Thunderbird 扩展:AboutConfig(来自 https://mjg.github.io/AboutConfig/)和 External Editor(来自 https://globs.org/articles.php?lng=en&pg=8)。

  1. 使用您选择的方法将补丁准备为文本文件。

  2. 在打开撰写窗口之前,使用“编辑→账户设置”在要用于发送补丁的帐户的“组合 & 寻址”面板中取消选中“组合 HTML 格式的邮件”设置。

  3. 在主 Thunderbird 窗口中,在打开补丁的撰写窗口之前,使用“工具→about:config”将以下设置设置为指定值:

    	mailnews.send_plaintext_flowed  => false
    	mailnews.wraplength             => 0
  4. 打开一个撰写窗口,然后单击外部编辑器图标。

  5. 在外部编辑器窗口中,读取补丁文件并正常退出编辑器。

旁注:可能可以使用 about:config 和以下设置来完成第 2 步,但目前还没有人尝试过。

	mail.html_compose                       => false
	mail.identity.default.compose_html      => false
	mail.identity.id?.compose_html          => false

contrib/thunderbird-patch-inline 脚本可以帮助您轻松地将补丁包含在 Thunderbird 中。要使用它,请执行上述步骤,然后使用该脚本作为外部编辑器。

KMail

这将帮助您使用 KMail 以内联方式提交补丁。

  1. 将补丁准备为文本文件。

  2. 点击“新建邮件”。

  3. 在“撰写器”窗口的“选项”下,确保“自动换行”未被选中。

  4. 使用“消息 → 插入文件…”并插入补丁。

  5. 回到撰写窗口:根据需要向邮件添加其他文本,完成地址和主题字段,然后按发送。

基础树信息

基础树信息块用于让维护者或第三方测试人员知道补丁系列适用的确切状态。它由基础提交组成,这是一个众所周知的提交,是项目稳定历史的一部分,所有其他人都在此基础上工作;以及零个或多个先决补丁,它们是正在进行中的、尚未包含在基础提交中的众所周知的补丁,需要在应用补丁之前按拓扑顺序应用到基础提交之上。

基础提交显示为“base-commit: ”后跟提交对象名的 40 个十六进制字符。先决补丁显示为“prerequisite-patch-id: ”后跟 40 个十六进制字符的补丁 ID,可以通过将补丁通过 git patch-id --stable 命令获得。

想象一下,在公共提交 P 之上,您应用了其他人提供的知名补丁 X、Y 和 Z,然后构建了您的三补丁系列 A、B、C,历史将是这样的:

---P---X---Y---Z---A---B---C

使用 git format-patch --base=P -3 C(或其变体,例如带有 --cover-letter 或使用 Z..C 而非 -3 C 来指定范围),基础树信息块显示在命令输出的第一个消息的末尾(第一个补丁或封面信),如下所示:

base-commit: P
prerequisite-patch-id: X
prerequisite-patch-id: Y
prerequisite-patch-id: Z

对于非线性拓扑,例如:

---P---X---A---M---C
    \         /
     Y---Z---B

您还可以使用 git format-patch --base=P -3 C 为 A、B 和 C 生成补丁,并且 P、X、Y、Z 的标识符会附加在第一个消息的末尾。

如果命令行中设置了 --base=auto,它将自动计算基础提交,作为远程跟踪分支的顶端提交与命令行中指定的 revision-range 的合并基础。对于本地分支,您需要通过 git branch --set-upstream-to 使其跟踪远程分支,然后才能使用此选项。

示例

  • 提取 revision R1 和 R2 之间的提交,并使用 git am 将它们应用到当前分支,以 cherry-pick 它们。

    $ git format-patch -k --stdout R1..R2 | git am -3 -k
  • 提取当前分支中存在但 origin 分支中不存在的所有提交。

    $ git format-patch origin

    为每个提交在当前目录中创建一个单独的文件。

  • 提取自项目创建以来导致 origin 的所有提交。

    $ git format-patch --root origin
  • 与前一个相同。

    $ git format-patch -M -B origin

    此外,它还会智能地检测和处理重命名和完全重写,以生成重命名补丁。重命名补丁可以减少输出的文本量,并通常使审查更容易。请注意,非 Git 的“patch”程序将无法理解重命名补丁,因此仅在使用接收者使用 Git 应用您的补丁时才使用它。

  • 提取当前分支的三个顶层提交,并将它们格式化为可电子邮件发送的补丁。

    $ git format-patch -3

注意事项

请注意,format-patch 将从输出中省略合并提交,即使它们是所请求范围的一部分。简单的“补丁”不包含足够的信息,以便接收端能够重现相同的合并提交。

GIT

Git[1] 套件的一部分