- 从.git来分析git工作原理,及命令背后做了什么事情
- 进而对git原理和使用能更得心应手
- 为了方便阅读和理解,分成两个维度来分析
- 从正面角度,从init到add到commit角度出发分析
- 从逆向角度,撤销角度出发分析
- 为了更直观,这边以文本描述和截图来描述
一、正面角度,从init到add到commit
一、基本理解操作篇
1、git init // 此时,查看.git里面的内容
2、添加一些内容,如a.j中添加,然后git add . // 再查看.git里面的内容(发现多了Index及objects里面多了一个文件夹)
//通过命令来查看这个二进制文件里面存储的是什么内容
3、查看Index内容:git ls-files -s
4、查看某个hash名对应的内容:git cat-file -p 这里为Hash值
// 总结:
1、git add 命令背后逻辑为:
// ① 文件内容存储在Objects文件内,hash前两位为文件夹名称,后面剩余的38位为文件名称
// ② index中记录最新的hash值
2、可以发现,,其实git就是key-value形式
记录的是hash值,然后通过hash值找到存储在objects中对应的该内容(value内容)
index记录暂存区用的是哪些hash组成的文件(key值)
二、hash生成规律篇及多次add 做了什么
1、a.js继续添加,然后git add . // 查看Index内容:git ls-files -s
2、增加b.js及大量内容,然后git add . // 查看Index内容:git ls-files -s
3、在b.js中增加少了内容然后git add . // 可以发现不是在之前基础上的+改动。而是此时完整的内容
// 总结:
1、hash值是和该文件的内容相关的,内容不变,hash值也不会变,也不会额外生成hash内容
2、index记录的是此次add的所有文件的最新Hash值,没有修改的部分,计算出来的hash不变
3、add相当于会对修改的文本,做一次内容拷贝
三、git commit -m 做了什么
1、git commit -m "init"
2、再次add . 再次commit 看效果
// 查看 commit 后会生成提交hash,对应我们可以看该Hash内容
// 查看Index内容:git ls-files -s
// 查看.git\refs\heads\master内容,发现保存的是最新的提交commit对应的hash值
// 总结:
1、git commit 会生成一个提交的hash
2、内容有tree,parent,提交用户,提交时间,提交message等。
3、其中tree记录的是此时暂存区index的内容
4、parent记录的是上个commit节点的Hash值(链式查找)
5、这个key存储在当前分支树那里,即当前为.git\refs\heads\master那里
// 即:commit是将此次的index暂存区的内容作为快照
// 加上提交的其它信息,生成一个提交记录(有Hash名,和objects中的内容存储)
四、查看git commit --amend 做了什么
1、添加内容 git add .
2、git commit --amend
// 查看
// 1、发现生成了新的commit信息(hash key和value)
// 2、.git\refs\heads\master记录的是新的hash
// 3、查看内容,parent和之前commit节点指向的是同一个,说明是修改当前提交节点信息,而不是新建
// 总结
// 相当于修改当前提交tree,而不是创建新的commit节点
五、切换分支,看做了什么事情
1、git checkout -b feature/1
// 查看
// 1、HEAD文件内容:ref: refs/heads/feature1 // 这里记录的是当前指向节点在哪
// 2、到.git\refs\heads\feature1 直接查看内容,发现是从切出位置的提交commmit对应hash值
二、从逆向角度,撤销角度出发分析(我觉得用恢复比较好理解)
一、恢复工作区(从暂存区回退)
二、恢复暂存区(从commit回退)
我们发现,因为每次add,其实没有生成新的节点来记录,只是修改Index
所以,不能恢复多次add后的某个add阶段!
即:多次add,恢复是从commit来恢复的,所以恢复到第0个add阶段,而不能恢复到第n个恢复阶段
三、从远程仓库恢复