git 暂存区

都说 git 分为三个区域,即所谓工作区、暂存区、版本库三部分,就像如下图所示(图片来源于 https://blog.csdn.net/qq_32452623/article/details/78417609 ):
在这里插入图片描述
一个 git 工程中,工作区很好理解,就是我们编辑代码的地方,版本库似乎也很好理解,就是 .git 目录,这个目录中有很多文件和子目;如果整个 .git 目录就是版本库,那暂存区在哪里?
其实上面的画法不是很正确,或者上面的理解不是很正确。如果认为 git 有三个区域,那所谓的版本库版本库并不是 .git 目录,整个目录实际上是暂存区和版本库一起的一个大目录,随便进一个 .git 目录都可以看到有如下内容:
在这里插入图片描述
这是一个 git 工程中版本管理工作的地方,其中的 index 是个文件,这实际上就是暂存区;当然不能把剩下的文件都理解为版本库。有一种理解方式是下图(图片来源于 https://www.runoob.com/git/git-workspace-index-repo.html ),把暂存区理解为版本库的一部分,倒也不是不行。

在这里插入图片描述
这个 index 文件与相应的分支或者 commit 是对应的,我们每次 add 时,都是往该文件中添加一些关于 add 的文件的信息。当一个文件都没有被添加到暂存区时,该文件并不存在。
该文件是二进制文件,其中的内容无法直接读取,可以使用 hexdump 工具以 16 进制形式读取,如下图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/319728b7a04f4cab95380abe93846bd0.png

该文件的信息如下,更具体的情况可以参考这篇文章

1 索引标志符

该部分占据 index 文件最开始的12个字节,前4个字节为固定的 0x44495243, 表示"DIRC"(DirCache的缩写);
中间4个字节表示版本号;
最后的4个字节表示被索引文件的数目;

2 状态数据

这部分存储每个被跟踪文件的状态信息,是 index 中的主体部分。

2.1 64位文件创建时间

8字节,表示文件被创建的时间戳,以纳秒位单位,前四节为秒,后四节为纳秒;

2.2 64位文件修改时间

8字节,表示文件上次被修改的时间戳,以纳秒为单位,前四节为秒,后四节为纳秒;
当执行 git status 命令时,git 会对暂存区中存储文件的时间戳与文件当前相关的时间戳信息(除了时间戳,还有文件大小也会被参考)进行比对,如果不同,才会进一步计算文件的哈希值以确定是否有变动;
以下是个测试:

touch abc.txt # 先生成一个空文件
stat abc.txt # 获取文件的时间信息
git add abc.txt
git commit -m "test"
git status # 这里会显示暂存区很干净
touch abc.txt # 重置文件的创建和修改时间
stat abc.txt # 与之前的时间戳信息进行比对
git status # 发现暂存区依然为空

经过以上操作,可以发现,虽然文件的元信息发生了变化,但 git 并不 care 这个变化。

2.3 存储设备编号与 inode 编号

共8字节,前4字节表示设备编号,后4字节表示被截断的 inode 编号,这部分内容也只是用来辅助 git 判断,所以信息并不完整,甚至在 windows 上,这8个字节会直接被置位为0;

2.4 32位文件模式

共4字节,文件的读写执行权限;

2.5 32位用户 uid

共4字节,即 id -u 获取的用户 id,windows 上为0;

2.6 32位用户组 id

共4字节,即 id -g 获取到的值,windows 上同样为0;

2.7 32位文件大小

共4字节,以字节为单位;

2.8 160位哈希值

共20字节,即跟踪文件对应 blob 对象的 id;

2.9 16位对象状态

共2字节,内容比较多。

2.9.1 1位假定不变标志

表示忽略该文件所有变化,0表示跟踪所有修改,而1表示忽略所有更改;比如配置文件,一般配置文件在完成编辑并添加到 git 中后,很少会改动;但是测试过程中我们有时候又会不停去改动里边一些参数值,而改动完毕后,在提交时又得将该文件checkout回去,过程比较麻烦,可以使用 update-index 命令对该文件设置位不变标志:

git update-index --assume-unchanged XXX # 将文件设置为假定不变
git update-index --no-assume-unchanged XXX # 取消文件的假定不变设置

update-index 有很多参数,可以参考它的 help 信息。
如果想查看哪些文件被忽略了更改,可以使用

git ls-files -v  # 所有被标记了忽略的文件都是以小写字母开头

在这里插入图片描述

2.9.2 1位扩展标识

暂时无意义,置位为0;

2.9.3 2位阶段标志

合并分支时使用,因为暂存区会分为多个,类似于 redis 中数据库默认有16个一样,正常情况下,应该均为0,但合并时可能不为0;
在这里插入图片描述
当发生冲突时,情况就变为如下:
在这里插入图片描述

2.9.4 12位文件名长度

过长的文件名可能会被忽略部分内容;

2.10 可变长文件目录

这部分根据前边确定的文件名长度获取文件的名称,包括相对于 .git 的文件夹路径,但是要注意,这里会因为对其的要求,而在末尾进行0的填充,目测是按照4字节对齐;

2.11 32位分隔符

最多是32位,全部是0;需要与上面提到的可变长文件目录配合,分割不同文件的信息;要求每个文件的起始信息地址都是4的倍数。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值