git commit 命令捕获项目当前暂存变更的快照。提交的快照可以被视为项目的“安全”版本——除非您明确要求,否则 Git 永远不会更改它们。执行 git commit 之前,git add 命令用于提升或“暂存”对项目的变更,这些变更将存储在提交中。git commitgit add 这两个命令是最常用的两个命令。

Git 提交与 SVN 提交

虽然它们使用相同的名称,但 git commitsvn commit 完全不同。对于具有 svn 背景的 Git 新手来说,这个共同的术语可能会让人感到困惑,强调其差异非常重要。比较 git commitsvn commit 就是比较集中式应用模型 (svn) 和分布式应用模型 (Git)。在 SVN 中,提交将变更从本地 SVN 客户端推送到远程集中式共享 SVN 存储库。在 Git 中,存储库是分布式的,快照提交到本地存储库,这完全不需要与其他 Git 存储库进行交互。之后可以将 Git 提交推送到任意远程存储库。

工作原理

从高层次上讲,可以将 Git 视为时间线管理实用程序。提交是 Git 项目时间线的核心构建块单元。可以将提交视为 Git 项目时间线上的快照或里程碑。使用 git commit 命令创建提交,用于捕获项目当时的状态。Git 快照始终提交到本地存储库。这与 SVN 有根本的不同,在 SVN 中,工作副本提交到中央存储库。相比之下,在您准备好之前,Git 不会强迫您与中央存储库进行交互。就像暂存区是工作目录和项目历史记录之间的缓冲区一样,每个开发人员的本地存储库也是他们的贡献与中央存储库之间的缓冲区。

这改变了 Git 用户的基本开发模型。Git 开发人员有机会在本地代码存储库库中累积提交,而不是进行变更并将其直接提交到中央代码存储库。与 SVN 式的协作相比,这有许多优点:它可以更轻松地将功能拆分为原子提交,将相关提交组合在一起,并在将其发布到中央存储库之前清理本地历史记录。它还允许开发人员在隔离的环境中工作,推迟集成,直到他们可以方便地与其他用户合并。隔离和延迟集成对个人有利,而频繁集成和分成小单位符合团队的最大利益。有关 Git 团队协作最佳实践的更多信息,请阅读团队如何构建 Git 工作流程

快照,而不是差异

除了 SVN 和 Git 之间的实际区别外,它们的底层实现还遵循完全不同的设计理念。SVN 跟踪文件的差异,而 Git 的版本控制模型则基于快照。例如,SVN 提交包含与添加到存储库的原始文件相比的差异。而 Git 会在每次提交中记录每个文件的全部内容。

Git 教程:快照,而不是差异

这使得许多 Git 操作比 SVN 快得多,因为不必从其差异中“汇编”文件的特定版本——每个文件的完整版本可以立即从 Git 的内部数据库中获得。

Git 的快照模型几乎对其版本控制模型的各个方面都产生了深远的影响,影响了从分支和合并工具到协作工作流程的所有方面。

常用选项

git commit

提交暂存的快照。这将启动文本编辑器,提示您输入提交消息。输入消息后,请保存文件并关闭编辑器以创建实际提交。

git commit -a

提交工作目录中所有变更的快照。这仅包括对跟踪文件的修改(在历史记录中的某个时刻使用 git add添加的文件)。

git commit -m "commit message"

一种快捷命令,可立即创建带有传递提交消息的提交。默认 git commit 将打开本地配置的文本编辑器,并提示输入提交消息。传递 -m 选项将放弃文本编辑器提示,转而使用内联消息。

git commit -am "commit message"

组合了 -a-m 选项的高级用户快捷命令。这种组合会立即创建所有分阶段变更的提交,并获取内联提交消息。

git commit --amend

此选项为提交命令添加了另一层功能。传递此选项将修改上次提交。分阶段的变更将添加到先前的提交中,而不是创建新提交。此命令将打开系统配置的文本编辑器并提示变更先前指定的提交消息。

示例

使用提交保存变更

以下示例假设您已经编辑了当前分支上名为 hello.py 的文件中的某些内容,并准备将其提交到项目历史记录中。首先,您需要使用 git add 暂存文件,然后才能提交暂存的快照。

git add hello.py

此命令会将 hello.py 添加到 Git 暂存区域。我们可以使用 git status 命令检查此操作的结果。

git status
On branch main
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
   new file: hello.py

绿色输出新文件:hello.py 表示 hello.py 将在下次提交时保存。通过执行以下命令从提交中创建:

git commit

这将打开一个文本编辑器(可通过 git config 自定义),要求提供提交日志消息以及正在提交的内容列表:

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch main
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
#modified: hello.py

Git 不要求提交消息遵循任何特定的格式限制,但规范格式是用少于 50 个字符在第一行汇总整个提交,留一个空行,然后详细解释发生了什么变化。例如:

Change the message displayed by hello.py

- Update the sayHello() function to output the user's name
- Change the sayGoodbye() function to a friendlier message

使用提交消息的第一行作为主题行是一种常见的做法,类似于电子邮件。日志消息的其余部分被视为正文,用于传达提交变更集的详细信息。请注意,许多开发人员也喜欢在提交消息中使用现在时态。这使得它们读起来更像是存储库上的操作,让许多历史记录重写操作更加直观。

如何更新(修改)提交

继续上面的 hello.py 示例。我们进一步更新 hello.py 并执行以下命令:

git add hello.py
git commit --amend

这将再次打开配置的文本编辑器。但是,这次它将预先填充我们之前输入的提交消息。这表明我们不是在创建新提交,而是在编辑最后的提交。

摘要

git commit 命令是 Git 的核心主要功能之一。需要事先使用 git add 命令来选择将在下次提交时暂存的变更。然后,使用 git commit 在 Git 项目历史记录的时间线上创建分阶段变更的快照。在随附的页面上了解有关 git add 用法的更多信息。git status 命令可用于探索暂存区域和待处理提交状态。

SVN 和 Git 的提交模型有很大的不同,但由于术语相同,常常会混淆。如果您是从个人使用 SVN 转向 Git,不妨了解一下,在 Git 中提交成本很低,应该经常使用。虽然 SVN 提交是发出远程请求的昂贵操作,但 Git 提交是在本地使用更高效的算法完成的。

准备好了解 Git 了吗?

试用本交互式教程。

立即开始