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

名称

git-commit - 将变更记录到仓库

概要

git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]
	   [--dry-run] <commit>_ | --fixup [(amend|reword):"><commit>]
	   [-F <file> | -m <msg>] [--reset-author] [--allow-empty]
	   [--allow-empty-message] [--no-verify] [-e] [--author=<author>]
	   [--date=<date>] [--cleanup=<mode>] [--[no-]status]
	   [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]
	   [(--trailer <token>[(=|:)<value>])…​] [-S[<keyid>]]
	   [--] [<pathspec>…​]

描述

创建一个新的提交,其中包含暂存区的当前内容和描述变更的给定日志消息。新提交是 HEAD 的直接子节点(通常是当前分支的顶端),并且该分支会被更新以指向该提交(除非工作区没有关联的分支,在这种情况下,HEAD 会处于“游离”状态,如 git-checkout[1] 中所述)。

要提交的内容可以通过以下几种方式指定:

  1. 在运行 commit 命令之前,使用 git-add[1] 逐步向暂存区中“添加”变更(注意:即使是被修改的文件也必须进行“添加”);

  2. 同样在运行 commit 命令之前,使用 git-rm[1] 从工作区和暂存区中删除文件;

  3. 将文件作为参数列在 commit 命令后面(不使用 --interactive--patch 参数),在这种情况下,提交将忽略暂存区中已暂存的变更,而是记录所列文件的当前内容(这些文件必须已被 Git 追踪);

  4. 在运行 commit 命令时使用 -a 参数,自动“添加”所有已知文件(即已列在暂存区中的所有文件)的变更,并自动“删除”暂存区中已在工作区中被删除的文件,然后执行实际提交;

  5. 在运行 commit 命令时使用 --interactive--patch 参数,在完成操作之前,逐个决定除暂存区内容之外,还有哪些文件或区块应当作为提交的一部分。请参阅 git-add[1] 的“交互模式”部分,了解如何操作这些模式。

可以使用 --dry-run 选项,通过提供相同的一组参数(选项和路径),来获取上述任何方式为下一次提交所包含内容的摘要。

如果您进行了提交,紧接着发现了一个错误,您可以通过 git reset 进行恢复。

选项

-a
--all

自动暂存已被修改和删除的文件,但不受您未告知 Git 的新文件的影响。

-p
--patch

使用交互式补丁选择界面来选择要提交的变更。有关详细信息,请参阅 git-add[1]

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

生成带有 <n> 行上下文的 diff。上下文行数默认为 diff.context,如果未设置该配置变量,则默认为 3。(由于历史原因,不带 <n>-U 被静默接受为 -p 的同义词)。

--inter-hunk-context=<n>

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

-C <提交>
--reuse-message=<提交>

获取一个现有的 <提交> 对象,并在创建提交时重用其日志消息和作者信息(包括时间戳)。

-c <提交>
--reedit-message=<提交>

类似于 -C,但使用 -c 会调用编辑器,以便用户可以进一步编辑提交消息。

--fixup=[(amend|reword):]<提交>

创建一个新的提交,在使用 git rebase --autosquash 时会“修复(fix up)” <提交>。单纯的 --fixup=<提交> 会创建一个“fixup!”提交,该提交会更改 <提交> 的内容,但保持其日志消息不变。--fixup=amend:<提交> 类似,但它会创建一个“amend!”提交,该提交还会将 <提交> 的日志消息替换为“amend!”提交的日志消息。--fixup=reword:<提交> 会创建一个“amend!”提交,该提交会将 <提交> 的日志消息替换为其自身的日志消息,但不对 <提交> 的内容做任何更改。

由单纯的 --fixup=<提交> 创建的提交,其标题由“fixup!”后跟 <提交> 的标题组成,并会被 git rebase --autosquash 特殊识别。可以使用 -m 选项来补充所创建提交的日志消息,但一旦“fixup!”提交被 git rebase --autosquash 合并(squash)到 <提交> 中,额外的注释就会被丢弃。

--fixup=amend:<提交> 创建的提交与之类似,但其标题的前缀是“amend!”。<提交> 的日志消息会被复制到“amend!”提交的日志消息中,并在编辑器中打开以便进行润色。当 git rebase --autosquash 将“amend!”提交合并到 <提交> 中时,<提交> 的日志消息会被来自“amend!”提交的润色后的日志消息所替换。除非指定了 --allow-empty-message,否则“amend!”提交的日志消息为空是错误的。

--fixup=reword:<提交>--fixup=amend:<提交> --only 的简写。它会创建一个仅包含日志消息的“amend!”提交(忽略暂存区中暂存的任何变更)。当被 git rebase --autosquash 合并时,它会替换 <提交> 的日志消息,而不进行任何其他更改。

在由 git rebase --autosquash 应用时,“fixup!”和“amend!”提交都不会更改 <提交> 的作者信息。有关详细信息,请参阅 git-rebase[1]

--squash=<提交>

构建一个用于 git rebase --autosquash 的提交消息。提交消息的标题取自指定的提交,并带有“squash! ”前缀。可以与其他提交消息选项结合使用(-m/-c/-C/-F)。有关详细信息,请参阅 git-rebase[1]

--reset-author

当与 -C/-c/--amend 选项一起使用时,或者在冲突的 cherry-pick 之后进行提交时,声明生成的提交的作者身份现在属于提交者(committer)。这也会更新作者时间戳。

--short

在进行空运行(dry-run)时,以短格式提供输出。有关详细信息,请参阅 git-status[1]。隐式启用 --dry-run

--branch

即使在短格式中,也显示分支和跟踪信息。有关详细信息,请参阅 git-status[1]

--porcelain

在进行空运行时,以易于脚本解析的 porcelain 格式提供输出。有关详细信息,请参阅 git-status[1]。隐式启用 --dry-run

--long

在进行空运行时,以长格式提供输出。这是 git-status[1] 的默认输出。隐式启用 --dry-run

-z
--null

当显示 shortporcelain 格式的 git-status[1] 输出时,逐字打印文件名并以 NUL 而不是 LF 结束条目。如果未给出格式,则隐式使用 --porcelain 输出格式。在不使用 -z 选项的情况下,带有“异常”字符的文件名将按照配置变量 core.quotePath 的说明进行引用(参见 git-config[1])。

-F <文件>
--file=<文件>

<文件> 中获取提交消息。使用 - 从标准输入中读取消息。

--author=<作者>

覆盖提交的作者。使用标准的 A U Thor <author@example.com> 格式指定显式作者。否则,假定 <作者> 是一个模式,并用于搜索该作者已有的提交(即 git rev-list --all -i --author=<作者>);然后从找到的第一个此类提交中复制提交作者。

--date=<日期>

覆盖提交中使用的作者日期。

-m <消息>
--message=<消息>

<消息> 用作提交消息。如果给出了多个 -m 选项,它们的值将被连接为独立的段落。

The -m 选项与 -c-C 以及 -F 互斥。

-t <文件>
--template=<文件>

编辑提交消息时,用 <文件> 中的内容启动编辑器。通常使用 commit.template 配置变量向命令隐式提供此选项。项目可以使用这种机制,为参与者提供一些关于在消息中按什么顺序写什么的提示。如果用户在未编辑消息的情况下退出编辑器,提交将被中止。当通过其他方式(例如使用 -m-F 选项)指定消息时,此选项没有效果。

-s
--signoff
--no-signoff

在提交日志消息的末尾添加提交者的 Signed-off-by 尾部。Signoff 的含义取决于您正在提交到的项目。例如,它可能证明提交者有权在项目的许可证下提交工作,或者同意某些贡献者表示,例如开发者证书(请参阅 https://developercertificate.org 获取 Linux 内核和 Git 项目使用的证书)。请查阅您贡献项目的文档或领导层,以了解该项目如何使用 Signoff。

可以使用 --no-signoff 选项来抵消命令行中较早的 --signoff 选项。

Git 现在没有(将来也不会有)用于默认启用 --signoff 命令行选项的配置变量;详见 gitfaq[7] 中的 commit.signoff 条目。

--trailer <标记>[(=|:)<值>]

指定一个应作为尾注(trailer)应用的 (<标记>, <值>) 对。(例如:git commit --trailer "Signed-off-by:C O Mitter \ <committer@example.com>" --trailer "Helped-by:C O Mitter \ <committer@example.com>" 将向提交消息中添加 Signed-off-by 尾注和 Helped-by 尾注。)可以使用 trailer.* 配置变量(git-interpret-trailers[1])来定义是否省略重复的尾注、每个尾注在尾注序列中的出现位置以及其他细节。

-n
--verify
--no-verify

绕过 pre-commitcommit-msg 钩子。另请参阅 githooks[5]

--allow-empty

通常,记录一个与其唯一父提交具有完全相同树的提交是一个错误,该命令会阻止您进行此类提交。此选项绕过了这一安全保护,主要用于外部 SCM 接口脚本。

--allow-empty-message

创建一个空提交消息的提交,而无需使用像 git-commit-tree[1] 这样的底层命令。与 --allow-empty 类似,该命令主要供外部 SCM 接口脚本使用。

--cleanup=<模式>

确定在提交之前如何清理提供的提交消息。 <模式> 可以是 stripwhitespaceverbatimscissorsdefault

strip

去除开头和结尾的空行、尾随空格、注释,并将连续的空行合并。

whitespace

strip 相同,但不会删除 # 注释。

verbatim

完全不改变消息内容。

scissors

whitespace 相同,但在需要编辑消息时,会截断下方找到的行(及该行本身)之后的所有内容。“#”可以通过 core.commentChar 进行自定义。

# ------------------------ >8 ------------------------
default

如果需要编辑消息,则与 strip 相同。否则与 whitespace 相同。

默认值可以通过 commit.cleanup 配置变量进行更改(参见 git-config[1])。

-e
--edit

允许用户进一步编辑从 <文件>(通过 -F <文件>)、命令行(通过 -m <消息>)以及 <提交>(通过 -C <提交>)中获取的消息。

--no-edit

使用选定的提交消息,而不启动编辑器。例如,git commit --amend --no-edit 会在不修改其提交消息的情况下修正一个提交。

--amend

通过创建一个新的提交来替换当前分支的顶端。记录的树照常准备(包括 -i-o 选项以及显式路径规格的效果),当没有通过命令行选项(如 -m-F-c 等)指定其他消息时,原始提交的消息将用作起点,而不是空消息。新提交具有与当前提交相同的父提交和作者(--reset-author 选项可以推翻此行为)。

它粗略地等同于:

	$ git reset --soft HEAD^
	$ ... do something else to come up with the right tree ...
	$ git commit -c ORIG_HEAD

但可以用于修正合并提交。

如果您修正了一个已经发布的提交,您应该理解重写历史的后果。(参见 git-rebase[1] 中的“从上游变基中恢复”部分。)

--no-post-rewrite

绕过 post-rewrite 钩子。

-i
--include

在利用目前已暂存的内容进行提交之前,还要暂存命令行上给出的路径的内容。这通常不是您想要的,除非您正在结束一个有冲突的合并。

-o
--only

通过获取命令行上指定的路径的已更新工作区内容来进行提交,忽略为其他路径暂存的任何内容。如果在命令行上指定了任何路径,这是 git commit 的默认操作模式,在这种情况下可以省略此选项。如果此选项与 --amend 一起指定,则不需要指定路径,这可以用于修正上一次提交,而无需提交已经暂存的变更。如果与 --allow-empty 一起使用,同样不需要路径,并且将创建一个空提交。

--pathspec-from-file=<文件>

<文件> 中传递路径规格,而不是通过命令行参数。如果 <文件> 正好是 -,则使用标准输入。路径规格元素由 LFCR/LF 分隔。路径规格元素可以按照配置变量 core.quotePath 的说明进行引用(参见 git-config[1])。另请参见 --pathspec-file-nul 和全局 --literal-pathspecs

--pathspec-file-nul

仅在与 --pathspec-from-file 一起使用时有意义。路径规范元素由 NUL 字符分隔,所有其他字符都被视为字面值(包括换行符和引号)。

-u[<模式>]
--untracked-files[=<模式>]

显示未追踪的文件。

<模式> 参数是可选的(默认为 all),用于指定未追踪文件的处理方式;当不使用 -u 时,默认值为 normal,即显示未追踪的文件和目录。

可选的选项有:

no

不显示未追踪的文件

normal

显示未追踪的文件和目录

all

同时显示未追踪目录中的单个文件。

布尔值 true 的所有常用拼写都视为 normal,而 false 则视为 no。可以使用 git-config[1] 中记录的 status.showUntrackedFiles 配置变量来更改默认值。

-v
--verbose

在提交消息模板的底部,显示 HEAD 提交与将要提交的内容之间的统一差异(unified diff),以提醒用户该提交有哪些变更,从而帮助其描述提交。请注意,此差异输出的行前缀没有 #。此差异不会成为提交消息的一部分。请参阅 git-config[1] 中的 commit.verbose 配置变量。

如果指定两次,还会额外显示将要提交的内容与工作树文件之间的统一差异,即对已追踪文件的未暂存变更。

-q
--quiet

抑制提交摘要消息。

--dry-run

不创建提交,而是显示将要提交的路径列表、带有将保持未提交状态的本地变更的路径列表以及未追踪的路径列表。

--status

在使用编辑器准备提交消息时,在提交消息模板中包含 git-status[1] 的输出。默认开启,但可用于覆盖配置变量 commit.status

--no-status

在使用编辑器准备默认提交消息时,不要在提交消息模板中包含 git-status[1] 的输出。

-S[<密钥 ID>]
--gpg-sign[=<密钥 ID>]
--no-gpg-sign

对提交进行 GPG 签名。<密钥 ID> 是可选的,默认值为提交者身份;如果指定,它必须紧贴选项,中间不能有空格。--no-gpg-sign 可用于推翻 commit.gpgSign 配置变量和先前的 --gpg-sign

--

不再将任何后续参数解释为选项。

<路径规格>...

在命令行上给出 <路径规格> 时,仅提交与路径规格匹配的文件内容,而不记录已添加到暂存区的变更。这些文件的内容还将在之前已暂存内容的基础上,暂存以供下一次提交。

有关更多详细信息,请参阅 gitglossary[7] 中的 pathspec 条目。

示例

在记录您自己的工作时,工作区中修改后文件的内容将通过 git add 临时存储到一个称为“暂存区(index)”的临时存储区域。可以使用 git restore --staged <文件> 将文件在暂存区(而非工作区)中恢复为上一次提交的状态,这实际上撤销了 git add,并防止对该文件的更改参与下一次提交。使用这些命令逐步构建好要提交的状态后,使用 git commit(不带任何路径名参数)来记录目前已暂存的内容。这是该命令最基本的形式。例如:

$ edit hello.c
$ git rm goodbye.c
$ git add hello.c
$ git commit

您也可以告诉 git commit 自动留意工作区中已追踪文件的更改,并为您执行相应的 git addgit rm,而无需在每次单独更改后手动暂存文件。也就是说,如果您的工作区中没有其他更改,以下示例的效果与先前的示例相同:

$ edit hello.c
$ rm goodbye.c
$ git commit -a

命令 git commit -a 首先查看您的工作区,注意到您修改了 hello.c 并删除了 goodbye.c,并为您执行必要的 git addgit rm

在暂存了许多文件的更改后,您可以通过向 git commit 提供路径名来改变记录更改的顺序。当给出路径名时,该命令会创建一个仅记录对命名路径所做更改的提交。

$ edit hello.c hello.h
$ git add hello.c hello.h
$ edit Makefile
$ git commit Makefile

这将创建一个记录对 Makefile 的修改的提交。为 hello.chello.h 暂存的更改不包括在生成的提交中。然而,它们的更改并没有丢失——它们仍然处于暂存状态,只是被扣留了。在上述序列之后,如果您运行:

$ git commit

这第二个提交将按预期记录对 hello.chello.h 的更改。

在合并(由 git mergegit pull 发起)因冲突而停止后,干净合并的路径已为您暂存以待提交,而发生冲突的路径则保持未合并状态。您必须首先使用 git status 检查哪些路径存在冲突,并在工作区中手动修复它们后,像往常一样使用 git add 暂存结果:

$ git status | grep unmerged
unmerged: hello.c
$ edit hello.c
$ git add hello.c

在解决冲突并暂存结果后,git ls-files -u 将不再提及冲突的路径。完成后,运行 git commit 最终记录合并:

$ git commit

与记录您自己的更改的情况一样,您可以使用 -a 选项来省去输入。一个区别是,在合并解决期间,您不能使用带有路径名的 git commit 来改变提交更改的顺序,因为合并应该记录为单个提交。事实上,在给出路径名时,该命令会拒绝运行(但请参阅 -i 选项)。

提交信息

如果设置了以下环境变量,则作者和提交者信息将从中获取:

  • GIT_AUTHOR_NAME

  • GIT_AUTHOR_EMAIL

  • GIT_AUTHOR_DATE

  • GIT_COMMITTER_NAME

  • GIT_COMMITTER_EMAIL

  • GIT_COMMITTER_DATE

(注:“<”、“>”和“\n”会被去除)

按照惯例,作者和提交者姓名是某种形式的个人姓名(即其他人称呼您的名字),尽管 Git 并不强制或要求任何特定的形式。只要符合上述限制,可以使用任意 Unicode 字符。此姓名对身份验证没有影响;有关身份验证,请参阅 git-config[1] 中的 credential.username 变量。

如果未设置(其中某些)环境变量,则信息将从配置项 user.nameuser.email 中获取,或者(如果不存在)从环境变量 EMAIL 中获取,或者(如果未设置)从系统用户名和用于发送邮件的主机名中获取(获取自 /etc/mailname,如果该文件不存在,则回退到完全限定域名)。

如果设置了 author.namecommitter.name 及其对应的电子邮件选项,它们将覆盖 user.nameuser.email,而它们自身又会被环境变量覆盖。

典型的用法是仅设置 user.nameuser.email 变量;其他选项则是为更复杂的使用场景提供的。

日期格式

GIT_AUTHOR_DATEGIT_COMMITTER_DATE 环境变量支持以下日期格式:

Git 内部格式

格式为 <unix-timestamp> <time-zone-offset>,其中 <unix-timestamp> 是自 UNIX 纪元以来的秒数。<time-zone-offset> 是相对于 UTC 的正或负偏移量。例如,CET(比 UTC 早 1 小时)是 +0100

<unix 时间戳> 前面加上 @(例如,@0 +0000)会更安全,这会强制 Git 将其解释为原始时间戳。对于小于 100,000,000 的值(不足 9 位数字),这是必需的,以避免与其他日期格式(如 YYYYMMDD)混淆。

RFC 2822

RFC 2822 所描述的标准日期格式,例如 Thu, 07 Apr 2005 22:13:13 +0200

ISO 8601

由 ISO 8601 标准指定的日期和时间,例如 2005-04-07T22:13:13。解析器也接受用空格代替 T 字符。小数秒将被忽略,例如 2005-04-07T22:13:13.019 将被视为 2005-04-07T22:13:13

注意
此外,日期部分支持以下格式:YYYY.MM.DDMM/DD/YYYYDD.MM.YYYY

除了识别上述所有日期格式外,--date 选项还会尝试理解其他更人性化的日期格式,例如相对日期“yesterday”(昨天)或“last Friday at noon”(上周五中午)。

讨论

虽然不是强制要求的,但一个好的做法是:在提交消息的开头用一个简短的单行(不超过 50 个字符)总结变更,接着是一个空行,然后是更详尽的描述。提交消息中直到第一个空行之前的文本将被视为提交标题,并且该标题在整个 Git 中都会被使用。例如,git-format-patch[1] 将提交转换为电子邮件,它将标题用作主题(Subject)行,将提交的其余部分用作正文。

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

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

  • 路径名以 UTF-8 规范形式 C 进行编码。这适用于 tree 对象、索引文件、引用名称,以及命令行参数、环境变量和配置文件(.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 Porcelain 都被设计为不强制项目使用 UTF-8。如果某个项目的参与者发现使用遗留编码更方便,Git 并不禁止。但是,有几点需要注意。

  1. git commitgit commit-tree 会在提交日志消息看起来不像有效的 UTF-8 字符串时发出警告,除非你明确声明你的项目使用遗留编码。通过在 .git/config 文件中设置 i18n.commitEncoding 来声明,例如:

    [i18n]
    	commitEncoding = ISO-8859-1

    使用上述设置创建的提交对象会将其 i18n.commitEncoding 的值记录在它们的 encoding 头中。这是为了帮助以后查看它们的人。缺少此头表示提交日志消息是 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_EDITOR 环境变量、core.editor 配置变量、VISUAL 环境变量或 EDITOR 环境变量。有关详细信息,请参阅 git-var[1]

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

commit.cleanup

此设置会覆盖 git commit--cleanup 选项的默认值。当您总是希望在日志消息中保留以注释字符(core.commentChar,默认为 #)开头的行时,更改默认值会很有用,在这种情况下,您可以运行 git config commit.cleanup whitespace(请注意,如果这样做,您必须自己删除提交日志模板中以注释字符开头的帮助行)。

commit.gpgSign

一个布尔值,用于指定是否所有提交都应进行 GPG 签名。在执行变基(rebase)等操作时使用此选项可能会导致大量的提交被签名。使用代理(agent)可以方便地避免多次输入您的 GPG 密码。

commit.status

一个布尔值,用于启用/禁用在使用编辑器准备提交消息时在提交消息模板中包含状态信息。默认为 true

commit.template

指定用作新提交消息模板的文件路径名。

commit.verbose

一个布尔值或整数,用于指定 git commit 的详细程度。

钩子

此命令可以运行 commit-msgprepare-commit-msgpre-commitpost-commitpost-rewrite 钩子。有关更多信息,请参阅 githooks[5]

文件

$GIT_DIR/COMMIT_EDITMSG

此文件包含正在进行的提交的提交消息。如果 git commit 在创建提交之前因错误而退出,则用户提供的任何提交消息(例如在编辑器会话中)都将在此文件中可用,但会被下一次调用 git commit 所覆盖。

GIT

Git[1] 套件的一部分