前言
终于算是摸爬滚打的学会了基本的上传下载,但是每次都 add、commit、push机械性的敲难免会产生疑惑,为什么一开始就在文件夹里的东西既要add还要commit,为什么不能直接push。
而且一旦遇到冲突也不懂得解应该怎么解决,或者使用很低级的办法去解决。
这一切还是归咎于对于git机制的不够熟悉,于是这一次我们围绕本地文件来深入理解一下。
一、git整个上传过程的思路
摒弃繁杂的概念,一图即可
表面上看,我们只是把一个要上传的文件丢到文件夹里,然后一顿add、commit、push,文件就自己跑到github或者一些平台上面了,但其实整个过程的每一步都有它所做的事情。
图中的四个红框代表一个流程中的四个关键节点。
- 最右边的
工作区
代表你本地的文件夹,是最直观的文件夹,我们看的见,平时要上传的文件就直接放到这里。 暂存区
我们不能很直观地看到,属于隐藏文件夹中的内容。本地仓库
我们不能很直观地看到,属于隐藏文件夹中的内容。远程仓库
就是那些诸如github之类的远程平台,我们可以很清楚的看到里面有什么。
隐藏文件夹
是什么,就是程序进行一些自我配置、日志记录或者缓存之类的东西,隐藏的原因就是这类文件对用户使用电脑意义不大,只有专业人员会用到。
git同样具有这样的文件夹,我们打开系统显示隐藏文件夹的选项之后,这里出现了一个 .git
文件夹,这就是我们这次的目标。
二、.git文件夹解析
这个文件夹什么时候产生?他是我们在进行git init
时会产生。表明这个文件夹已经变成了 git 的工作区,各种与git相关的操作信息都会记录在.git
文件夹。
这里用一次文件上传为例,探究一下变化过程。
第一步
我们在初始化之后什么都不做,点进去看看,可以看到这里有很多东西,接下来我们来仔细看看。
HEAD文件
通过cat HEAD命令查看之后,我们发现它代表当前工作分支
- description 代表仓库描述信息,对我们来说作用不是很大,用到再研究
- config文件 代表一些仓库配置,比如邮箱什么的。
- info文件夹代表一些其他配置,例如排除规则(就是你上传时一个文件夹内的那些文件不要上传),属于高级用法,后续用到再研究。
- hooks文件夹存放一些脚本,属于高级用法,后续用到再研究。
- object文件夹存放git对象,因为现在是空的,后面研究。
第二步
剩下的文件夹里的文件夹都是空的,我们先继续往下操作看看会发生什么。
首先git add
一下,我们发现这里多出来一个index
文件夹,这就是我们说的是暂存区
,经过git add
之后的文件会存储到这里。
除此之外,我们发现了object文件夹
里多出来一个git对象(整个文件夹),里面存储的是文件内容。
所以:
index文件
:是本地暂存区,存储暂存信息
第三步
接下来我们git commit
一下看看
我们发现本地有四个
文件夹的时间戳都被改变了。
首先,logs文件夹
,这是个保存所有更新引用记录的文件夹,约等于日志,内部的具体文件先不深究,以后研究。
其次,objects文件夹
,里面多出来两个新的git对象
多出了两个的原因是每一次git操作都会产生一个对象,而git commit的底层其实是两条指令,今天先不深究。
【 引用大佬解释 】
先通过git write-tree
命令,把暂存区中的索引信息,生成一个tree对象存储到本地版本库中。
然后通过git commit-tree
命令,把上面生成的树对象进行封存,生成一个commit对象,存储到本地版本库中。
然后,就是COMMIT_EDITMSG文件
,我们打开看看,发现里面写的是最新一次git commit -m "xxx"
的注释内容。
最后,index文件
的内容因为被推送到本地仓库,所以需要做个标记代表已经操作过,更新一下文件。
所以:
logs文件夹
:保存所有更新引用记录的文件夹COMMIT_EDITMSG文件
:最新一次 commit 的注释内容
到这里为止,文件已经存储到本地仓库了,我们继续往下操作。
第四步
首先我们git remote add
添加一下远程仓库的地址,我们发现config
文件的更新时间变化了,这说明所有配置相关信息都与config
文件有关。
打开看看,可以看到刚刚添加的仓库地址
接下来我们同步一下远程仓库git pull
一下,我们发现本地有六个文件发生了变化。
object文件夹
更新git对象
refs文件夹
更新了引用,这里先不深究。
FETCH_HEAD
是一个版本链接,指向着目前已经从远程仓库取下来的分支的末端版本
HEAD文件
因为拉取了仓库文件,所以操作对象不是本地的文件,因此发生改变。
ORIG_HEAD
当前commit对象的前一个commit对象hash值,与logs/HEAD文件的最新一行的第一个hash值保持一致。
最后,我们git push
一下
发现config文件
更新了,打开看看我们可以发现多出来一些。
所以:
FETCH_HEAD
是一个版本链接,指向着目前已经从远程仓库取下来的分支的末端版本ORIG_HEAD
当前commit对象的前一个commit对象hash值,与logs/HEAD文件的最新一行的第一个hash值保持一致。
小结
通过我们的实践,我们可以发现所谓的分布式存储的过程,就是根据不同的操作改变不同文件里的标记,例如git操作多以哈希值为代表。通过一个简单的上传实例让我加深了对于git的理解。