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

名称

git-commit - 记录对仓库的变更

概要

git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]
	   [--dry-run] <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]

-C <commit>
--reuse-message=<commit>

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

-c <commit>
--reedit-message=<commit>

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

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

创建一个新提交,当使用 git rebase --autosquash 应用时,它会“修正” <commit>。纯粹的 --fixup=<commit> 会创建一个“fixup!”提交,它改变 <commit> 的内容但保留其日志消息不变。--fixup=amend:<commit> 类似但创建一个“amend!”提交,它还会将 <commit> 的日志消息替换为“amend!”提交的日志消息。--fixup=reword:<commit> 创建一个“amend!”提交,它将其自身的日志消息替换 <commit> 的日志消息,但不对 <commit> 的内容做任何更改。

由纯粹的 --fixup=<commit> 创建的提交,其标题由“fixup!”和 <commit> 的标题组成,并被 git rebase --autosquash 特殊识别。-m 选项可用于补充所创建提交的日志消息,但一旦“fixup!”提交被 git rebase --autosquash 压缩到 <commit> 中,这些额外的注释将被丢弃。

--fixup=amend:<commit> 创建的提交类似,但其标题前缀为“amend!”。<commit> 的日志消息被复制到“amend!”提交的日志消息中并在编辑器中打开,以便可以进行修改。当 git rebase --autosquash 将“amend!”提交压缩到 <commit> 中时,<commit> 的日志消息将被“amend!”提交中修改后的日志消息替换。如果“amend!”提交的日志消息为空,除非指定了 --allow-empty-message,否则会报错。

--fixup=reword:<commit>--fixup=amend:<commit> --only 的简写。它创建一个只有日志消息的“amend!”提交(忽略索引中任何已暂存的变更)。当被 git rebase --autosquash 压缩时,它会替换 <commit> 的日志消息而不会进行任何其他变更。

“fixup!”和“amend!”提交在被 git rebase --autosquash 应用时都不会改变 <commit> 的作者信息。详见 git-rebase[1]

--squash=<commit>

构造用于 git rebase --autosquash 的提交消息。提交消息标题取自指定提交,并加上前缀“squash! ”。可与额外提交消息选项(-m/-c/-C/-F)一起使用。详见 git-rebase[1]

--reset-author

-C/-c/--amend 选项一起使用时,或在冲突的 cherry-pick 之后提交时,声明结果提交的作者现在属于提交者。这也会更新作者时间戳。

--short

在试运行时,以短格式输出。详见 git-status[1]。隐含 --dry-run

--branch

即使在短格式中,也显示分支和跟踪信息。

--porcelain

在试运行时,以“瓷器”友好格式输出。详见 git-status[1]。隐含 --dry-run

--long

在试运行时,以长格式输出。隐含 --dry-run

-z
--null

显示 shortporcelain 状态输出时,按字面打印文件名并以 NUL 终止条目,而不是 LF。如果未给出格式,则隐含 --porcelain 输出格式。如果没有 -z 选项,带有“不寻常”字符的文件名将按照配置变量 core.quotePath 的说明进行引用(参见 git-config[1])。

-F <file>
--file=<file>

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

--author=<author>

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

--date=<date>

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

-m <msg>
--message=<msg>

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

-m 选项与 -c-C-F 互斥。

-t <file>
--template=<file>

编辑提交消息时,使用 <file> 中的内容启动编辑器。commit.template 配置变量通常用于隐式地向命令提供此选项。此机制可用于希望指导参与者如何按顺序编写消息的项目。如果用户在未编辑消息的情况下退出编辑器,则提交将被中止。当通过其他方式提供消息时,例如通过 -m-F 选项,此功能无效。

-s
--signoff
--no-signoff

在提交日志消息末尾添加提交者的 Signed-off-by 尾部信息。签名的含义取决于您提交的项目。例如,它可能证明提交者有权根据项目许可证提交作品,或同意某些贡献者声明,如开发者原创证书。(有关 Linux 内核和 Git 项目使用的证书,请参阅 https://developercertificate.org)。请查阅您所贡献项目的文档或领导层,以了解该项目中如何使用签名。

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

--trailer <token>[(=|:)<value>]

指定应作为尾部信息应用的(<token><value>)对。(例如,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
--[no-]verify

绕过 pre-commitcommit-msg 钩子。另见 githooks[5]

--allow-empty

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

--allow-empty-message

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

--cleanup=<mode>

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

strip

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

whitespace

strip 相同,但 #注释不被移除。

verbatim

完全不改变消息。

scissors

whitespace 相同,但如果消息要被编辑,则从(包括)以下行开始的所有内容都被截断。“#”可以通过 core.commentChar 自定义。

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

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

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

-e
--edit

允许用户进一步编辑从 <file> 处通过 -F <file> 获取的消息,从命令行通过 -m <message> 获取的消息,以及从 <commit> 处通过 -C <commit> 获取的消息。

--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] 中的“从上游 rebase 恢复”一节。)

--no-post-rewrite

绕过 post-rewrite 钩子。

-i
--include

在从已暂存内容创建提交之前,也暂存命令行上给定的路径内容。这通常不是您想要的,除非您正在结束一个冲突的合并。

-o
--only

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

--pathspec-from-file=<file>

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

--pathspec-file-nul

仅在使用 --pathspec-from-file 时有意义。路径规范元素用 NUL 字符分隔,所有其他字符都按字面解释(包括换行符和引号)。

-u[<mode>]
--untracked-files[=<mode>]

显示未跟踪文件。

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

可能的选项有

no

不显示未跟踪文件

normal

显示未跟踪文件和目录

all

也显示未跟踪目录中的单个文件。

所有通常表示布尔值 true 的拼写都被视为 normalfalse 被视为 no。默认值可以通过 git-config[1] 中记载的 status.showUntrackedFiles 配置变量更改。

-v
--verbose

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

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

-q
--quiet

抑制提交摘要消息。

--dry-run

不创建提交,但显示将要提交的路径列表,将保留未提交的本地更改路径以及未跟踪的路径。

--status

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

--no-status

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

-S[<key-id>]
--gpg-sign[=<key-id>]
--no-gpg-sign

使用 GPG 签名提交。<key-id> 是可选的,默认为提交者身份;如果指定,它必须紧跟在选项后,不能有空格。--no-gpg-sign 对于抵消 commit.gpgSign 配置变量和之前指定的 --gpg-sign 都很有用。

--

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

<pathspec>...

当在命令行上给出 <pathspec> 时,提交与路径规范匹配的文件的内容,而不记录已添加到索引的变更。这些文件的内容也会被暂存,以便在已暂存内容的基础上进行下一次提交。

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

示例

当记录您自己的工作时,您工作树中已修改文件的内容会通过 git add 临时存储到一个称为“索引”的暂存区。一个文件可以被恢复到上次提交的状态,但仅限在索引中,不在工作树中,使用 git restore --staged <file>,这实际上撤销了 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 选项还会尝试理解其他更以人为中心的日期格式,例如“昨天”或“上周五中午”之类的相对日期。

讨论

尽管并非强制要求,但最好以一行简短(不超过 50 个字符)的摘要来开始提交消息,后跟一个空行,然后是更详细的描述。提交消息中第一个空行之前的文本被视为提交标题,该标题在整个 Git 中使用。例如,git-format-patch[1] 将提交转换为电子邮件,它将标题用作主题行,其余提交内容用作正文。

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 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_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] 套件的一部分

scroll-to-top