English ▾ 主题 ▾ 最新版本 ▾ git-commit 上次更新于 2.49.0

名称

git-commit - 记录对存储库的更改

概要

git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend] [--dry-run] [(-c | -C | --squash) <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 开关,自动“添加”来自所有已知文件的更改(即,所有已经列在索引中的文件),并自动“rm”索引中已从工作树中删除的文件,然后执行实际的提交;

  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!” 提交中的精简日志消息替换。 除非指定了 --allow-empty-message,否则 “amend!” 提交的日志消息为空是一个错误。

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

当由 git rebase --autosquash 应用时,无论是 “fixup!” 还是 “amend!” 提交都不会更改 *<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

在进行 dry-run 时,以简短格式给出输出。 有关详细信息,请参见 git-status[1]。 隐含 --dry-run

--branch

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

--porcelain

在进行 dry-run 时,以一种适合 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 尾部。 签名的含义取决于您正在提交到的项目。 例如,它可以证明提交者有权根据项目的许可提交工作,或同意某些贡献者代表,例如开发者原创证书。(请参阅 https://developercertificate.org,了解 Linux 内核和 Git 项目使用的证书。)请查阅您要贡献的项目的文档或领导层,以了解在该项目中如何使用签名。

可以使用 --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 相同,只是不删除 #commentary。

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] 中的“从上游变基中恢复”部分。)

--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>,则提交与 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 选项还将尝试理解其他更以人为中心的日期格式,例如相对日期,如“yesterday”或“last Friday at noon”。

讨论

虽然不是必需的,但最好用一个简短的(不超过 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 选项的默认值。 当您始终希望在日志消息中保留以注释字符 # 开头的行时,更改默认值会很有用,在这种情况下,您将执行 git config commit.cleanup whitespace(请注意,如果这样做,您将必须自己删除提交日志模板中以 # 开头的帮助行)。

commit.gpgSign

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

commit.status

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

commit.template

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

commit.verbose

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

HOOKS

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

FILES

$GIT_DIR/COMMIT_EDITMSG

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

GIT

属于 git[1] 套件的一部分

scroll-to-top