1. 一切皆commit
HEAD:当前分支头结点
branch:指向目标分支的最新提交,当目标分支有了新的提交,则 git 自动更新这个分支指针,以指向最新的提交。
tag:对某个提交或分支打 tag 之后,将固定指向那个提交,后续即使分支有更新甚至删除,tag 所指向的提交不变,且一直存在
分支branch,标签tag,当前提交HEAD 这些,本质上都是指向某个提交的引用,即:一切都是 commit
参考文章 https://www.cnblogs.com/jasongrass/p/10582449.html
2. git 区域:工作区域,暂存区,版本库
- Working Tree 当前的工作区域
- Index/Stage 暂存区域,和git stash命令暂存的地方不一样。使用git add xx,就可以将xx添加进Stage里面
- Repository 版本库,提交历史,即使用git commit提交后的结果
文件存入Repository流程
以下简单敘述一下把文件存入Repository流程:
刚开始 working tree 、 index 与 repository(HEAD)里面的內容都是一致的
当git管理的文件夹里面的内容出现改变后,此時 working tree 的內容就会跟 index 及 repository(HEAD)的不一致,而Git知道哪些文件(Tracked File)被改动过,哪些文件是新添加的(Untracked Files),哪些文件被删除了,直接将工作区状态标记为 Changes not staged for commit 。
当我们执行 git add 后,会将这些改变的文件內容加入 stage 中 (Staged files),所以此时working tree跟 stage 的內容是一致的,但他们与repository(HEAD)內容不一致。
接着执行 git commit 后,将 git 索引中所有改变的文件內容提交至 Repository 中,建立出新的 commit 节点(HEAD)后, working tree 、 index 与repository(HEAD)区域的内容 又会保持一致。
暂存区其实就是.git目录下的index文件
参考文章 Git Reset 三种模式:https://www.jianshu.com/p/c2ec5f06cf1a
参考文章 关于Git暂存区的理解: https://www.cnblogs.com/cposture/p/4178003.html
3. git 对象:数据对象blob,树对象tree,提交对象commit
git 本质上是一个基于键值对的文件系统,你可以向其中插入任意类型的内容,它会返回一个键值,通过该键值可以在任意时刻再次检索该内容。PS:下面提到的命令了解即可
3.1 数据对象blob
每一个blob对象存的是文件的内容,是一个二进制数据,它并不存改变,也不存文件名,Blob对象和其所对应的文件所在路径、文件名是否被更改都完全没有关系。因为blob对象内容全部都是数据,同样的内容对应同样的key,如果两个文件在一个目录树(或是一个版本仓库)中有同样的数据内容,那么它们将会共享同一个blob对象。任意一个单独的blob对象都无法反应git数据库的版本全部信息。
git hash-object -w --stdin 向git数据库中写入内容,该命令返回一个40位的sha-1哈希密码值,为此次写入的key,每次调用此命令都会产生一个数据对象,它被放在.git/objects目录下,以前两位哈希值作为目录名,后38位作为文件名。此命令是直接对git数据库进行操作,不涉及到暂存区。
git cat-file -p key 查看此key对应的对象详细信息
git cat-file -t key 查看此key对应的对象类型
git show key 查看此key对应的对象的内容
另:git add命令并不是直接操作暂存区,而是先创建blod对象(git hash-object -w)放入objects目录下,然后更新暂存区(git update-index ),然而并不是每次add都会创建blod对象(但是必定每次都会更新暂存区),如果有内容相同的blob对象已存在,则共用同一个对象。
3.2 树对象tree
git 利用树对象来进行文件名保存,相当于一个目录项,一个树对象可以包含一条或多条记录(每条记录存有指向一个指向数据对象或子树对象的sha-1key指针、以及相应的文件模式、类型、以及文件名信息)一个数对象还可以包含另一个树对象。
树对象可以将多个文件组织到一起(暂存区功能),所以它与暂存区有关,查看暂存区内容命令 git ls-files -s
readme.txt是已提交的文件,newFile.txt是新添加的文件,说明提交不会清除暂存区信息,100644表示文件模式为普通文件
另:git commit 提交可简单分为两步,更新暂存区 git update-index ,创建树对象 git write-tree, 将当前暂存区状态生成快照,并写入仓库中,他会将树对象与暂存区内所有blob对象进行关联。每次commit会生产一个树对象以及一个提交对象
添加子树对象 git read tree 将树对象放入暂存区
查看树对象 git show key 或者 git ls-tree key
$ git ls-tree fb3a8bdd0ce
100644 blob 63c918c667fa005ff12ad89437f2fdc80926e21c .gitignore
100644 blob 5529b198e8d14decbe4ad99db3f7fb632de0439d .mailmap
100644 blob 6ff87c4664981e4397625791c8ea3bbb5f2279a3 COPYING
040000 tree 2fb783e477100ce076f6bf57e4a6f026013dc745 Documentation
100755 blob 3c0032cec592a765692234f1cba47dfdcc3a9200 GIT-VERSION-GEN
100644 blob 289b046a443c0647624607d471289b2c7dcd470b INSTALL
100644 blob 4eb463797adc693dc168b926b6932ff53f17d0b1 Makefile
100644 blob 548142c327a6790ff8821d67c2ee1eff7a656b52 README
一个tree对象包括一串(list)条目,每一个条目包括:mode、对象类型、SHA1值 和名字(这串条目是按名字排序的)。它用来表示一个目录树的内容。
当两个树对象的内容完全一致时,他们才会有同样的key,Git以此来快速的判断两个对象内容是否不同。
3.2 提交对象commit
commit对象指向一个tree对象,并且带有相关的描述信息。每次commit会生产一个树对象以及一个提交对象
一个提交(commit)由以下的部分组成:
一个 tree对象key(对应本次提交信息快照),父对象 (上一次提交信息),作者 ,提交者,注释信息
参考文章 http://gitbook.liuhui998.com/1_2.html
参考文章 https://www.cnblogs.com/jasongrass/p/10582465.html
4. git 中的文件状态
在工作区下的所有文件可划分为两种状态,已跟踪或未跟踪。
所有暂存区中未记录的文件都属于未跟踪状态。清空暂存区并提交,相当于删除所有文件(但本地文件会保留)
已跟踪的文件又分为,已提交Commited、已暂存Staged(对应符号A)、已修改但尚未暂存 3个状态
其中修改又可细分为,新增的未跟踪文件Untracked(对应符号?),删除DELETE(D),内容改动MODIFY(M)
使用git gtatus 命令可查看工作区状态 --short 表示一种简洁的输出格式,如:
$ git status --short
D apple.c
M hello.c
A world.c
AD world_bak.c
?? 123.txt