概述
下面记录了git的一些原理
暂存区
当执行git status命令(或者git diff命令)扫描工作区改动的时候,先依据.git/index文件中记录的(用于跟踪工作区文件的)时间戳、长度等信息判断工作区文件是否改变,如果工作去文件的时间戳改变了,说明文件的内容可能被改变了,说明文件的内容可能被改变了,需要打开文件,读取文件内容,与更改前的原始文件相比较,判断文件内容是否被更改。如果文件内容没有更改,则将该文件新的时间戳记录到.git/index文件中。因为如果要判断文件是否更改,使用时间戳、文件长度等信心进行比较要比通过文件内容荣比较要快得多,所以Git这样的实现方式可以让工作区状态扫描更快速地执行
.git/index实际上就是一个包含文件索引的目录树,向是一个虚拟的工作区。在这个虚拟工作区的目录树中,记录了文件名和文件的状态信息(时间戳和文件长度等)。文件的内容并没有存储在其中,而是保存在Git对象库.git/objects目录中,文件索引建立了文件和对象库中对象实体之间的对应
左侧是工作区,右侧是版本库,版本库中标记为index的区域是暂存区,标记为master的是master分支所代表的目录树
HEAD实际是指向master分支的一个"游标"
objects表示的区域为Git的对象库,实际位于.git/objects目录下
当对工作区修改(或新增)的文件执行git add命令时,暂存区的目录树将被更新,同时工作区修改(或新增)的文件内容会被写入到对象库中的一个新对象中,而该对象的ID被记录在暂存区的文件索引中
当执行提交操作(git commit)时,暂存区的目录树会写道版本库中,master分支会指向最新提交时暂存区的目录树
当执行git reset HEAD命令时,暂存区的目录树会被重写,会被master分支指向的目录树所替换,但是工作区不受影响
当执行git rm --cached 命令时,会直接从暂存区删除文件,工作区则不做出改变
当执行git checkout或 git checkout –命令时,会用暂存区全部的文件或指定的文件替换工作区的文件。这个操作很危险,会清楚工作区中未添加到暂存区的改动
当执行git checkout HEAD 或git checkout HEAD fiel命令时,会用HEAD指向的master分支中的全部或部分文件替换暂存区和工作区中的文件
git中的对象及关系
如果想查看暂存区的目录树,需要先将暂存区的目录树写入Git对象库,(用git write-tree命令),然后针对该目录树执行git ls-tree tree_Id命令
git write-tree 输出的是写入Git对象库中的Tree ID,这个ID将作为下一条命令输入
git ls-tree为查看目录树
哈希(hash)是一种数据摘要算法(或称散列算法),是信息安全领域中重要的理论基石。该算法将任意长度的输入经过散列运算转换为固定长度的输出。固定长度的输出可以称为对应输入内容的数字摘要或哈希值。SHA1摘要算法可以处理从0到两百多万TB的输入数据,输出为固定的160比特的数字摘要。
SHA1哈希值由40个十六进制的数字组成。每个十六进制的数字相当于一个4位的二进制数字。
从提交开始可以建立一条历史跟踪链,master可以指向最新提交,使用.git/refs/heads/maser指向这个链条的的最先提交
.git/refs是保存引用的命名空间,.git/refs/heads目录下的引用又称为分支
git reset
refs/heads/master就好像是一个游标,可上,可下。Git提供了git reset命令,可以将"游标"指向任意一个存在的提交id,重置后曾经的修改会丢失
git reset --hard HEAD^:代表了HEAD的父提交,这条命令指将master重置到上一个的老的提交上
git提供了一个git relog命令,使用show子命令可以显示此文件的内容
git relog show master | head -5
git reset --hard master@{2}可以回滚
分离头指针的确可以将master分支重置到该测试提交上,但是会丢掉master提交的内容,可以使用合并
git merge commit_Id