简体中文 ▾ 主题 ▾ 最新版本 ▾ git-format-patch 最后更新于 2.53.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] 中的“SPECIFYING REVISIONS”部分)表示指定范围内的提交。

对于单个 <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] 的 DISCUSSION 部分)的行的串联。

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

如果给定 --threadgit-format-patch 将生成 In-Reply-ToReferences 头,使第二个和后续的补丁邮件显示为对第一个邮件的回复;这还会生成一个 Message-ID 头以供引用。

选项

-p
--no-stat

生成不带任何 diffstat 的纯补丁。

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

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

--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 图表的命令,而设置 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,还输出一个二进制 diff,可以使用 git-apply 应用。

--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 会忽略子模块工作树的所有更改,仅显示超级项目中存储的提交的更改(这是 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 头,使第二个和后续邮件显示为对第一个邮件的回复。还控制 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)显示为对给定 <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>

生成的输出文件名将在大约 <n> 字节处截断,而不是标准 64 字节(过短的值将默默提高到合理长度)。默认为 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 不完全相同,则在消息正文中放置一个包含原始作者的 From: 头。如果没有给出 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 补丁系列中唯一补丁的注释,显示先前版本的补丁系列与当前正在格式化的系列之间的差异。previous 是一个单一修订,命名先前系列的尖端,该系列与正在格式化的系列共享一个共同基准(例如 git format-patch --cover-letter --interdiff=feature/v1 -3 feature/v2)。

--range-diff=<previous>

作为审阅者辅助,在封面信中插入一个 range-diff(参见 git-range-diff[1]),或者作为 1 补丁系列中唯一补丁的注释,显示先前版本的补丁系列与当前正在格式化的系列之间的差异。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

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

预期的用例是为不属于提交日志消息本身的提交编写支持性解释,并将其与补丁提交一起包含。虽然可以在 format-patch 运行之后但在发送之前简单地编写这些解释,但将它们保留为 Git 注释可以使它们在补丁系列的不同版本之间保持不变(但请参阅 git-notes[1] 中关于 notes.rewrite 配置选项的讨论以使用此工作流)。

默认是 --no-notes,除非设置了 format.notes 配置。

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

为生成的每条消息添加签名。根据 RFC 3676,签名与正文之间用一行“-- ”分隔。如果省略签名选项,签名默认为 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>]

记录基础树信息以识别补丁系列适用的状态。有关详细信息,请参阅下面的基础树信息部分。如果 <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 邮箱格式,带有一个固定的“魔术”时间戳,表示该文件是 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/ 子目录,看看 patch 文件包含什么,并检查上面提到的常见损坏模式。

  • 同时,也要检查 infofinal-commit 文件。如果 final-commit 中的内容与您希望在提交日志消息中看到的内容不完全一致,则接收方在应用您的补丁时很可能会手动编辑日志消息。例如,补丁电子邮件中的“Hi, this is my first patch.\n”应该放在表示提交消息结束的三破折号行之后。

MUA 特有提示

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

GMail

Gmail 的网页界面无法关闭行自动换行,因此它会损坏您发送的任何电子邮件。但是,您可以使用 "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(附加组件)

安装可在 https://addons.thunderbird.net/thunderbird/addon/toggle-line-wrap 获取的 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-hex。先决条件补丁显示为“prerequisite-patch-id: ”,后跟 40-hex 补丁 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,它将自动计算基础提交,作为远程跟踪分支的尖端提交和命令行中指定的修订范围的合并基础。对于本地分支,您需要在使用此选项之前通过 git branch --set-upstream-to 使其跟踪远程分支。

示例

  • 提取修订版本 R1 和 R2 之间的提交,并使用 git am 将它们应用到当前分支以进行 cherry-pick

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

    $ git format-patch origin

    对于每个提交,将在当前目录中创建一个单独的文件。

  • 提取自项目启动以来导致 origin 的所有提交

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

    $ git format-patch -M -B origin

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

  • 从当前分支中提取最顶部的三个提交,并将其格式化为可发送电子邮件的补丁

    $ git format-patch -3

注意事项

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

GIT

Git[1] 套件的一部分