2. 向 Git 仓库提交更新记录

上节课我们创建了 my_project 这个本地仓库,但并没有将任何文件放入到仓库中。这节课我们来学习如何使用 Git 本地仓库对工作区中的文件进行管理。

首先我们在工作区 my_project 内创建一个文件 README.md 写入一行 # Git 教程。在我的 Ubuntu Linux 系统的电脑上操作如下:

weimingze@mzstudio:~/my_project$ echo -e -n "# Git 教程\r\n" > README.md
weimingze@mzstudio:~/my_project$ cat README.md
# Git 教程

Windows 用户请尝试使用 PowerShell 进行上述操作或使用记事本手动创建 README.md 文件。

我们上述创建的文件 README.md 只是在工作区中存在,并没有纳入到该 Git 本地仓库中进行管理。下面我们要做的就是将工作区内新添加的 README.md 文件形成一个快照提交到 Git 本地仓库中并形成一条提交记录,以便在需要时取出当前 README.md 文件的快照。在使用 Git 提交记录时会在本地仓库内创建一个提交对象,此提交对象用来记录本次提交的内容(当前工作区的变化信息)。

专业术语:

要了解 Git,你需要先了解 工作区 中的每个文件的状态有哪些。

工作区中每个文件都有两种状态中的一个:

  1. 已跟踪状态。
  2. 未跟踪状态。

已跟踪文件(Tracked files)是指 Git 知道这个文件,并此文件已经在本地仓库中形成快照或在暂存区中将放入到本地仓库中进行管理的文件。这样的文件是已跟踪状态

未跟踪文件(Untracked files) 是指没有纳入 Git 本地仓库管理的文件。也不在暂存区中管理的文件。这样的文件是未跟踪状态

上述我们创建的文件 README.md 此时就是未跟踪状态。如果我们要将其纳入版本控制中,我们需要将其变成已跟踪状态

已跟踪状态 又分为三种状态:

  1. 未修改状态(Unmodified)。
    • 当前工作区中的文件和本地仓库中的文件内容完全一致。当你首次克隆(复制)一个远程仓库时,你本地工作区中的所有的文件都是已跟踪且处于未修改状态。
  2. 已修改状态(Modified)。
    • 是指工作区中的文件内容和暂存区中文件内容不一致或暂存区文件内容和本地仓库中文件内容不一致的文件。
  3. 已暂存状态(Staged)。
    • 工作区中文件已经修改,并放入到暂存区中,工作区和暂存区中文件内容一致,但暂存区和本地仓库的内容不一致的文件。

专业术语:

它们的关系如下图所示:

声明周期

我们刚才创建的 README.md 就是未跟踪文件。如果我们要将其纳入版本控制我们需要将其变为 已跟踪文件

查看文件状态

此时我们可以使用 git status 查看当前工作区的文件状态。

git status 命令

git status 是用于查看工作区和暂存区的当前状态。

我的电脑上的查询结果如下:

weimingze@mzstudio:~/my_project$ git log
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    README.md

nothing added to commit but untracked files present (use "git add" to track)

我们可以看出文件 README.md未跟踪文件Untracked files),并提示使用 git add 命令可以将其变为 已跟踪状态

现在我们已经完成整个工作区文件的修改。我们准备将当前编写的 README.md 文件的状态做一个快照保存在本地仓库,完成一个备份操作。此时我们还要理解工作区、暂存区、本地仓库之间的关系。

一个本地仓库有三个部分构成:

  1. 工作区(Workspace):是存放当前代码的区域,是一个树形结构,也称为工作树( working tree),你可以理解成你工作的办公室或车间。
  2. 暂存区:你可以理解成存放运往本地仓库的文件的小货车,你要你发个git commit命令,这些数据就会发往本地仓库。
  3. 本地仓库:用于存放版本信息的仓库。

它们的关系如下:

+----工作区----+                +-----------------版本库----------------------+
| create file |                |  +--暂存区--+               +---仓库区----+  |
| delete file | <-- diff -------> |         | -- commit --> |            |  |
| modify file | --- add,rm,mv --> |         |               | git log    |  |
|             |                |  |         |               | git reflog |  |
| cur version | <-- restore ----- |         |<-- restore -- |            |  |
|             | <-- switch --- |  +---------+               +------------+  |
+-------------+                 +-------------------------------------------+

git add 命令

作用: 将一个或多个文件、文件夹、符号链接等加入暂存区,并变为已跟踪状态,准备提交。

命令格式

git add 文件或文件夹1 文件或文件夹2 ...

文件可以使用通配符,如 *.c表示所有以 .c 结尾的文件。

我们将之前 README.md 加入暂存区,执行结果如下:

weimingze@mzstudio:~/my_project$ git add README.md
weimingze@mzstudio:~/my_project$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
    new file:   README.md

现在 README.md 的文件已经加入到暂存区,变成已跟踪状态。提示为:新加入的文件(new file)。下一步我们就可以使用 git commit 命令将其提交到仓库了。

git commit 命令

`作用: 用于将暂存区内的数据提交到本地仓库,并形成版本信息。

git commit 常用的选项

选项
说明
-m "版本说明信息"
提交时附带当前提交的说明,如果不携带此参数,则会启动默认的文本编辑器,待编辑完成后再提交。
--amend
暂存区的内容提交到上一个版本(修订),不形成新的版本信息。

示例:

使用 git commit 命令将当前暂存区中的文件 README.md 提交到本地仓库,并形成提交对象。

weimingze@mzstudio:~/my_project$ git commit -m "魏明择在当前项目中添加了 README.md文件"
[master (root-commit) 8cb34d1] 魏明择在当前项目中添加了 README.md文件
 1 file changed, 1 insertion(+)
 create mode 100644 README.md

如出现上述提示,说明你已将完成了提交。其中 master 是你本地提交操作的分支(后面会讲)。其中提示中 8cb34d1 是本次提交在本地仓库中产生的提交对象的ID,它代表本次提交在本地仓库内产生的提交对象的唯一标识(后面回溯历史版本时会用到)。

提交对象ID

每次提交到本地仓库都会在本地仓库产生一个提交对象,这个提交对象记录本地提交的所有信息。每个提交对象有一个唯一的标识,即提交对象ID,如:8cb34d10643636d04286624adaa55b6a3967ab9e,这个哈希值就是本地提交对象的 ID,这个ID相当于这个提交对象的身份证号,并在整个仓库中不会重复。通常我们只用其中的前几位,如 8cb34d1 是这个哈希值的前 7 个数字,这几位只要不和其它的 ID 重复,它就可以代表这个提交对象了。

完成了本次提交以后我们在使用 git status 命令查看工作区和暂存区的状态如下:

weimingze@mzstudio:~/my_project$ git status
On branch master
nothing to commit, working tree clean

上述信息指出当前你正处于 master 分支(默认分支,后面会讲)上,目前没有任何数据需要提交,工作区是干净的。以上提示信息意味着当前已跟踪的所有文件都没有被修改,Git 也没有发现任何未跟踪的文件。即当前工作区所在的文件夹是一个干净的文件夹。否则这些文件会在运行 git status 命令时被列出。

如果你在提交过程中提示如下信息,则说明你需要设置你的用户信息。

weimingze@mzstudio:~/my_project$ git commit -m "魏明择在当前项目中添加了 README.md文件"
Author identity unknown

*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account's default identity.
Omit --global to set the identity only in this repository.

fatal: unable to auto-detect email address (got 'weimingze@mzstudio.(none)')

你需要使用上述命令来设置当前用户信息,以便 git 记录提交人是谁。设置方法详见 《Git 基本设置》这一小节

时隔一天,我又改写了上述 my_project 项目。我在 README.md 中添加了一行内容 作者:魏明择,内容如下:

文件 README.md 中的内容:

# Git 教程
作者:魏明择

同时我有添加了一个文件 website.txt ,其中的内容只是记录了一行我网站的网址,其内容如下:

https://weimingze.com

使用 git status 命令查看当前的状态如下:

weimingze@mzstudio:~/my_project$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   README.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    website.txt

no changes added to commit (use "git add" and/or "git commit -a")

可见现在项目中有一个未跟踪的文件 website.txt 和 已跟踪并已修改的的文件 README.md

现在我们将两个文件使用 git add README.md website.txt 命令重新添加到暂存区并查看状态如下:

weimingze@mzstudio:~/my_project$ git add README.md website.txt
weimingze@mzstudio:~/my_project$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    modified:   README.md
    new file:   website.txt

可见现在两个文件 README.mdwebsite.txt 都成为了已跟踪状态,并随时可以提交。接下来我们使用 git commit 命令进行提交。执行结果如下:

weimingze@mzstudio:~/my_project$ git commit -m "魏明择在当前项目中修改了 README.md 文件,并添加了 website.txt 文件"
[master 5dcccb0] 魏明择在当前项目中修改了 README.md 文件,并添加了 website.txt 文件
 2 files changed, 2 insertions(+)
 create mode 100644 website.txt
weimingze@mzstudio:~/my_project$ git status
On branch master
nothing to commit, working tree clean

本次提交的哈希值是 5dcccb0,本地提交的分支是 master 分支。提交完毕后当前工作区是干净的(没有任何修改没有提交)。

上述代码,我经历两天工作,完成了两个版本的提交。我们怎样才能查看我们提交的信息呢?下面我们学习 git log 命令。

git log 命令

作用: 用来查看当前分支的历史提交记录,以便提取过去存入仓库中的某个版本。

git log 常用选项

选项
说明
--pretty=oneline
每个提交日志以一行的形式显示,前面显示完整的提交哈希值,后面显示提交信息。
--oneline
以一行的形式显示,前面显示简短的提交哈希值,后面显示提交信息。
-n
n 为整数,表示最近的 n 次提交信息。
--abbrev-commit
使用短哈希值代替完整的 40 位提交哈希(默认 7 位)
--graph
在日志左侧以 ASCII 字符绘制提交历史图。
--all
显示所有分支的历史提交。

我们已经完成了两次提交,现在我们使用 git log 命令来查看我们过去有几次提交信息。

weimingze@mzstudio:~/my_project$ git log
commit 5dcccb02bd6e6593cdec017f9af4f910c0c01c3a (HEAD -> master)
Author: weimingze <auth@weimingze.com>
Date:   Sun Jan 11 18:50:28 2026 +0800

    魏明择在当前项目中修改了 README.md 文件,并添加了 website.txt 文件

commit 8cb34d10643636d04286624adaa55b6a3967ab9e
Author: weimingze <auth@weimingze.com>
Date:   Sat Jan 10 17:15:05 2026 +0800

    魏明择在当前项目中添加了 README.md文件

如果你的提交次数比较多,你想以最简单的方式来查看提交日志,可以使用 --pretty=oneline 选项简化显示内容。如下:

weimingze@mzstudio:~/my_project$ git log --pretty=oneline
5dcccb02bd6e6593cdec017f9af4f910c0c01c3a (HEAD, master) 魏明择在当前项目中修改了 README.md 文件,并添加了 website.txt 文件
8cb34d10643636d04286624adaa55b6a3967ab9e 魏明择在当前项目中添加了 README.md文件

使用 --oneline 选项显示的结果如下:

weimingze@mzstudio:~/my_project$ git log --oneline
5dcccb0 (HEAD, master) 魏明择在当前项目中修改了 README.md 文件,并添加了 website.txt 文件
8cb34d1 魏明择在当前项目中添加了 README.md文件

使用 --graph 选项显示的结果如下:

weimingze@mzstudio:~/my_project$ git log --graph
* commit 5dcccb02bd6e6593cdec017f9af4f910c0c01c3a (HEAD, master)
| Author: weimingze <auth@weimingze.com>
| Date:   Sun Jan 11 18:50:28 2026 +0800
| 
|     魏明择在当前项目中修改了 README.md 文件,并添加了 website.txt 文件
| 
* commit 8cb34d10643636d04286624adaa55b6a3967ab9e
  Author: weimingze <auth@weimingze.com>
  Date:   Sat Jan 10 17:15:05 2026 +0800

      魏明择在当前项目中添加了 README.md文件

使用 --abbrev-commit 选项显示的结果如下:

weimingze@mzstudio:~/my_project$ git log --abbrev-commit
commit 5dcccb0 (HEAD, master)
Author: weimingze <auth@weimingze.com>
Date:   Sun Jan 11 18:50:28 2026 +0800

    魏明择在当前项目中修改了 README.md 文件,并添加了 website.txt 文件

commit 8cb34d1
Author: weimingze <auth@weimingze.com>
Date:   Sat Jan 10 17:15:05 2026 +0800

    魏明择在当前项目中添加了 README.md文件

上述信息显示本地仓库 my_project 两次提交。最上面的是最近的提交,完整的哈希值是 5dcccb02bd6e6593cdec017f9af4f910c0c01c3a。下面的是稍远时间点的提交,哈希值是 8cb34d10643636d04286624adaa55b6a3967ab9e。上述信息还显示了每次提交的提交人、提交时间、提交备注的文字信息。其中 (HEAD -> master) 指示我们当前操作的位置指针 HEAD 是在 master 分支中的 5dcccb02bd6e6593cdec017f9af4f910c0c01c3a 提交对象的位置。即当前所处于的位置是在第二次提交中(即最新的一次提交)。

经历了两次提交,目前我们 本地仓库形成了如下的结构:

                 HEAD
                  |
              .--------.
              | master |
              `--------`
                  |
+-------+     +-------+
|8cb34d1| <-- |5dcccb0|
+-------+     +-------+
第一次提交      第二次提交

其中 8cb34d1 是第一次提交生成的提交对象,本次提交添加了一个文件 README.md5dcccb0 是第二次的提交对象,本次提交增加了一个文件 website.txt 并修改了文件 README.md 的内容。

附加信息:

以上两次提交都在主分支 master(默认分支)上进行。master 分支的分支指针 master 指向了第二次提交创建的提交对象 5dcccb0HEAD 是当前位置指针,它指向了分支指针 master,表示当前分支是 master 分支。

关于 HEAD 当前位置指针和分支指针后面会讲。

Git 命令一般有很多的选项,可以实现不同的功能。如 git log 命令可以使用 git log --help 来查看其所有选项和使用手册。

点击这里下载上述示例 my_project 本地仓库的代码

本节小结:

  1. git status 命令用于查看当前工作区的状态。
  2. git add 命令用于将文件加入到暂存区。为提交做准备。
  3. git commit 命令用于将暂存区的修改记录提交到本地仓库并创建提交记录。
  4. git log 命令用于显示提交日志。

实验:

再次修改 README.md 文件中的内容,然后提交到本地仓库。