简体中文 ▾ 主题 ▾ 最新版本 ▾ git-commit 最后更新于 2.53.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。

--inter-hunk-context=<n>

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

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

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

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

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

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

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

由单纯的 --fixup=<提交> 创建的提交标题由 "fixup!" 后跟 <提交> 的标题组成,并被 git rebase --autosquash 特殊识别。-m 选项可用于补充所创建提交的日志消息,但一旦 "fixup!" 提交被 git rebase --autosquash 合并到 <提交> 中,额外的注释将被丢弃。

--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 后进行提交时,声明结果提交的作者身份现在属于提交者。这也会更新作者时间戳。

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

当显示 shortporcelaingit-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 选项,它们的值将连接成单独的段落。

-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=<文件>

<文件> 中传递路径规范(pathspec),而不是使用命令行参数。如果 <文件> 正好是 -,则使用标准输入。路径规范元素由 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 的所有常用拼写都被视为 normalfalse 被视为 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 暂时存储到一个名为“索引”的暂存区。可以使用 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

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] 将提交转换为电子邮件,它将标题用于主题行,将其余的提交内容用于正文。

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)等操作时使用此选项可能会导致大量提交被签名。使用代理以避免多次输入 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] 套件的一部分