Git 暂存区

本贴最后更新于 2300 天前,其中的信息可能已经东海扬尘

Git 暂存区


1.1 一个文件三个版本

QQ 截图 20170908204816.png-18kB

上图中 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 高效原因之一。


QQ 截图 20170909163753.png-259.7kB

  • 版本库中标记为 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 对比暂存区和版本库中此文件的改动

  • Simon
    20 引用 • 10 回帖
  • Git

    Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

    209 引用 • 358 回帖 • 2 关注

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...