Git 暂存区
1.1 一个文件三个版本
上图中
M
的位置不同,add
到暂存区之前M
在第二列,add
到暂存区后M
在第一列。
M
第一列的含义是:版本库中的文件与处于中间状态——提交任务(暂存区)中的文件相比有改动
M
第二列的含义是:工作区当前的文件与处于中间状态——提交任务(暂存区)中的文件相比有改动
git add
将工作区中有改动的文件添加到提交任务(暂存区 stage)。这里使用提交任务
是因为一般 add 之后就 commit
若在 add
之后 commit
之前又修改了文件,那通过 git status
会看到两个改动信息。这个时候,此文件有三个版本;一个是版本库中最新版本,一个是暂存区中的版本,一个是工作区中的版本。三个版本,两两比较
1.2 理解 Git 暂存区
[root@izwz9f5nsv33jsmjcx0qw1z demo]# ll --full-time .git/index
-rw-r--r-- 1 root root 118 2017-09-09 16:21:54.408551770 +0800 .git/index
[root@izwz9f5nsv33jsmjcx0qw1z demo]# git status -s
[root@izwz9f5nsv33jsmjcx0qw1z demo]# ll --full-time .git/index
-rw-r--r-- 1 root root 118 2017-09-09 16:21:54.408551770 +0800 .git/index
[root@izwz9f5nsv33jsmjcx0qw1z demo]# touch demo.txt
[root@izwz9f5nsv33jsmjcx0qw1z demo]# ll --full-time .git/index
-rw-r--r-- 1 root root 118 2017-09-09 16:21:54.408551770 +0800 .git/index
[root@izwz9f5nsv33jsmjcx0qw1z demo]# git status -s
[root@izwz9f5nsv33jsmjcx0qw1z demo]# ll --full-time .git/index
-rw-r--r-- 1 root root 118 2017-09-09 16:24:01.783371216 +0800 .git/index
[root@izwz9f5nsv33jsmjcx0qw1z demo]#
以上这几个命令和结果说明,当执行 git status
命令扫描工作区改动的时候,先根据版本库中 .git/idnex
文件中记录的(用于记录跟踪工作区文件的)的时间戳、长度等信息判断工作区中此文件是否改动。如果工作区文件的时间戳或其它信息与版本库中此文件的信息对应不上,说明文件可能被改动了;此时再去对比文件内容,如果文件的内容没有改变,则将改文件新的相关信息记录到 .git/index
中。
通过根据文件相关信息判断文件是否被修改,比直接对比文件内容要快得多。Git 的这样实现方式可以让工作区状态扫描更快的执行。这也是 Git 高效原因之一。
- 版本库中标记为
index
的区域为暂存区,标记为master
的是 master 分支所代表的目录树。 - 图中看出,此时
HEAD
实际是指向 master 分支的一个游标,所以图示中出现的HEAD
的地方皆可以用 master 替代。 - 图中
objects
表示的区域为 Git 的对象库,实际位于.git/objcets
目录下, - 若工作区有改动,那么执行
git add
命令时,暂存区的目录树将被更新,同时工作区的改动内容会被写入到对象库
里一个新的对象中,而该对象的 ID 会被记录在暂存区的文件索引中。 - 当执行
git commit
时,暂存区的目录树会被写到版本库(对象库)中,master
分支会做相应的更新,即master
最新指向的目录树就是提交前原暂存区的
目录树。 - 当执行
git reset HEAD
时,暂存区的目录树将会被重写,会被 master 分支所指的目录树所替换。但工作区不受影响。 - 当执行
git rm --cached
直接从暂存区删除文件,工作区无变化 - 当执行
git checkout -- <file>
时,会用暂存区的文件覆盖工作区的文件。 - 当执行
git checkout HEAD .
或者git checkout HEAD -- <file>
时,会用 HEAD 所指向的 master 分支中的文件,覆盖暂存区
和工作区
中的文件。危险慎用。
2.1 Git Diff
2.1.1 工作区,暂存区,版本库的目录树浏览
工作区的目录树可以直接查看,就是目录下的那些。
git ls-tree -l HEAD
查看 HEAD(版本库中当前提交)指向的目录树。
但是,若想查看暂存区中的目录树,则需要:
第一步:git write-tree
将暂存区的目录树写入到objects
(Git 对象库)
第二步:git ls-tree -l treeID
上面一个操作返回一个 treeID
若查看暂存区所有文件可以用git ls-files
命令。
[root@izwz9f5nsv33jsmjcx0qw1z demo]# git add .
[root@izwz9f5nsv33jsmjcx0qw1z demo]# git status -s
M demo.txt
[root@izwz9f5nsv33jsmjcx0qw1z demo]# git write-tree
80f3dc01584b639b2692ae54f32603629ed612fb
[root@izwz9f5nsv33jsmjcx0qw1z demo]# git ls-tree -l 80f3dc01584b639b2692ae54f32603629ed612fb
100644 blob d9bb8b32d2f0bff87c03b30a7da0dc685b0b74f9 8 demo.txt
[root@izwz9f5nsv33jsmjcx0qw1z demo]#
2.1.2 三个版本,两两比较
git diff
对比工作区和暂存区中此文件的改动
git diff HEAD
对比工作区和版本库中此文件的改动
git diff --cached
对比暂存区和版本库中此文件的改动
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于