[toc]
前言
本系列文章是针对计算机经典书籍《Git 权威指南》的精简版学习笔记,方便大家快速了解内容以及速记,欢迎订阅
上一篇文章,我们学习了创建版本库的几个命令,不熟悉的同学可以参考 Git初始化
git log --stat- 可以看到每次提交的文件变更统计
5.1 修改不能直接提交吗
echo "Nice to meet you" >> welcome.txtgit diff- 可以看到修改后的文件与本库(与本地比较的不是版本库中的文件,而是一个中间状态的文件)中的文件的差异
- 工作区与提交任务中相比的差异
diff --git a/welcome.txt b/welcome.txt
index 18832d3..9c2a787 100644
--- a/welcome.txt
+++ b/welcome.txt
@@ -1 +1,2 @@
Hello.
+Nice to meet you
- 如果此时认为文件修改后可以直接提交,那就错了哦,
- 尝试运行命令:
git commit -m "Append a nice line." - 发现会运行不成功
- 提交日志里面没有新的提交记录出现
- 执行
git diff可以看到和之前一样的结果,说明没有提交成功 git status查看文件状态,可以看到文件处于修改状态,- 精简模式
git status -s
➜ git commit -m "Append a nice line."
On branch master
Changes not staged for commit:
modified: welcome.txt
no changes added to commit
- 所以如果想提交,需要利用
git add命令 git add welcome.txtgit diff HEAD- 工作区与HEAD相比
git diff --staged或git diff --cached- 提交暂存区与版本库中文件的差异
git status -s- M位于第一列的含义
M welcome.txt- 版本库中的文件与处于中间状态--提交任务(提交暂存区,stage)中的文件相比有改动
- M位于第二列的含义
- 工作区当前的文件与处于中间状态--提交任务(提交暂存区,stage)中的文件相比有改动
M welcome.txt- 如果此时继续修改welcome.txt 文件
echo "Bye-Bye." >> welcome.txtgit status -sMM welcome.txt- 不但版本库中最新提交的文件与处于 中间状态--提交任务(提交暂存区,stage)中的文件相比有改动,而且工作区当前的文件处于中间状态--提交任务(提交暂存区,stage)中的文件相比也有改动
- 现在再来提交
git commit -m "which version checked in?"- 如何证明提交成功呢
git log --pretty=onelinegit status -sgit diff
5.2 理解Git暂存区(stage)
git status 原理- 先依据.git/index文件中记录的时间戳,长度等信息判断工作区文件是否改变
- 如果工作区文件的时间戳改变了,说明文件的内容可能改变了,需要打开文件,读取文件内容,与源文件做比较,
- 如果文件内容没有改变,则将该文件新的时间戳记录到.git/index文件中
- 使用时间戳,文件长度等信息进行比较要比通过文件内容比较要快得多
.git/index- 实际是一个包含文件索引的目录树,像一个虚拟的工作区
- 记录了文件名和文件的状态信息(时间戳和文件长度,文件的内容没有存储在其中,而是保存在Git对象库.git/objects目录中)

- HEAD实际是指向master分支的一个 “游标”,所以图示的命令中出现HEAD的地方可以用master来替换
- 图中的objects标识的区域为Git的对象库,实际位于 .git/objects 目录下,这一点会在后面的章节中重点介 绍
- 当对工作区修改(或新增)的文件执行git add命令时,暂存区的目录树将会被更新,同时工作区修改(或新增)的文件内容会被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中
- 当执行提交操作(git commit)时,暂存区的目录树会写到版本库(对象库)中,master分支会做相应的更新,即master最新指向的目录树就是提交时原暂存区的目录树
- 当执行git reset HEAD 命令时,暂存区的目录树会被重写,会被master指向的目录树所替换,但是工作区不受影响
- 当执行git rm --cached
<file>命令时,会直接从暂存区删除文件,工作区则不做出改变 - 但执行git checkout ., 或git checkout --
<file>命令时,会用暂存区全部的文件或制定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动 - 但执行git checkout HEAD . 或git checkout HEAD
<file>命令时,会用HEAD指向的master分支中的全部或者部分文件替换暂存区和工作区中的文件,这个命令也是极具危险性的,因为不但会清除工作区中的未提交的改动,也会清除暂存区中未提交的改动
5.3 Git Diff魔法
1. 工作区,暂存区和版本库的目录树浏览
➜ git ls-tree -l HEAD
100644 blob 7e12803b85898fd0ae42d0a793c3eaf9f0cdd66e 28 test.ini
100644 blob 9c2a787a930a7b547abdf71e47ab1a67de890832 24 welcome.txt
-l参数可以显示文件的大小- 第一个字段是文件的属性(rw-r--r--)
- 第二个字段说明是Git对象库中的一个blob对象(文件),
- 第三个字段则是该文件在对象库中对应的ID--一个40位的SHA1哈希值格式的ID
- 第四个字段是文件大小
- 第五个字段是文件名
- 清除当前工作区中没有加入版本库的文件和目录(非跟踪文件和目录)
- git clean -fd
- 用暂存区内容刷新工作区
git checkout .
2. Git diff 魔法

- 工作区和暂存区比较
- git diff
- 暂存区和HEAD比较
- git diff --cached
- 工作区和HEAD比较
- git diff HEAD
5.4 不要使用git commit -a
- 好处
- 减少用git add 命令标识变更文件的步骤
- 坏处
- 丢掉Git暂存区带给用户的最大好处:对提交内容进行控制的能力
5.5 搁置问题,暂存状态
- git stash
- 保存当前共奏进度