简体中文 ▾ 主题 ▾ 最新版本 ▾ git-commit 上次更新于 2.52.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. 使用 git-add[1] 在使用 commit 命令之前增量地将更改“添加”到索引(注意:即使是已修改的文件也必须“添加”);

  2. 使用 git-rm[1] 在使用 commit 命令之前从工作树和索引中删除文件;

  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 <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!”提交,它还会用“amend!”提交的日志消息替换 <commit> 的日志消息。--fixup=reword:<commit> 创建一个“amend!”提交,它会用自己的日志消息替换 <commit> 的日志消息,但不会对 <commit> 的内容进行任何更改。

纯粹的 --fixup=<commit> 创建的提交的标题由“fixup!”后跟 <commit> 的标题组成,并被 git rebase --autosquash special 识别。-m 选项可用于补充创建的提交的日志消息,但当 git rebase --autosquash 将“fixup!”提交合并到 <commit> 时,额外的注释将被丢弃。

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

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

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

--squash=<commit>

构建一个用于 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

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

--porcelain

进行 dry-run 时,以 porcelain 可读的格式输出。有关详细信息,请参阅 git-status[1]。隐含 --dry-run

--long

进行 dry-run 时,以长格式输出。隐含 --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 尾部。Signoff 的含义取决于您正在提交到的项目。例如,它可能证明提交者有权在项目的许可证下提交工作,或者同意某些贡献者表示,例如开发者证书(请参阅 https://developercertificate.org 获取 Linux 内核和 Git 项目使用的证书)。请查阅您贡献项目的文档或领导层,以了解该项目如何使用 Signoff。

可以使用 --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
--verify
--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

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

--no-edit

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

--amend

通过创建新提交来替换当前分支的尖端。记录的树照常准备(包括 -i-o 选项以及显式路径名的影响),并且在没有通过命令行选项(如 -m-F-c 等)指定其他消息时,原始提交的消息被用作起点。

这大致等同于

	$ 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> 中传递 pathspec 而不是命令行参数。如果 <file> 恰好是 -,则使用标准输入。Pathspec 元素由 LFCR/LF 分隔。Pathspec 元素可以按 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 的所有常规拼写都按 normal 处理,falseno 处理。默认值可以通过 status.showUntrackedFiles 配置变量进行更改,该变量在 git-config[1] 中有文档记录。

-v
--verbose

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

如果指定两次,还显示将要提交的内容和工作树文件之间的统一 diff,即已跟踪文件的未暂存更改。

-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> 时,提交匹配 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 及其对应的 email 选项会覆盖已设置的 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 进行编码。这适用于 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] 套件的一部分