https://www.ruanyifeng.com/blog/2018/10/git-internals.html (阮一峰)
https://zhuanlan.zhihu.com/p/66506485 (知乎)
https://learngitbranching.js.org/(交互式学习git的网站)
https://backlog.com/git-tutorial/cn/stepup/stepup7_6.html (Git学习网站)
目录
总结
需要理解的重要概念
1).git目录及文件
.git/objects
数据库。工作目录里的所有文件,代码、库文件、图片等都会变成git对象存在这个objects目录下。每个文件都是一个二进制文件。可以通过 git cat-file -p SHA1值来查看文件的内容。.git/index
暂存区(索引),是一个二进制文件.使用git ls-files --stage可以查看操作的文件,git add将文件加入暂存区,git rm --cache将文件移出暂存区。.git/HEAD
一个符号引用(symbolic reference),指向当前所在的分支最新commit。 所谓符号引用,表示它是一个指向其他引用的指针。文件内容:ref: refs/heads/分支名
git checkout 分支2,文件内容就会更新为:ref: refs/heads/分支2
git commit 时,该命令会创建一个提交对象,并用 HEAD 文件中那个引用所指向的 SHA-1 值设置其父提交字段。
查看HEAD文件内容:cat .git/HEAD
或者git symbolic-ref HEAD
设置HEAD文件内容:git symbolic-ref HEAD refs/heads/test
,相当于git checkout test
。
查看HEAD指向的commit的sha1值:git rev-parse [--short] HEAD
,short参数表示显示短7位的sha1值。
一张图表明HEAD是指向当前所在的分支最新commit
但是当你checkout commit-id或者tag,HEAD就是指向某个具体的commit(tag也是一个commit,只是不可改变),查看HEAD文件内容就是这个commit的sha1值。
.git/refs
存储HEAD、tag及远程引用
2)工作区、暂存区、历史库
文件在各个区的转化对应的指令:
git add:将文件加入暂存区
git rm --cache:将文件移出暂存区。
3)git对象(blob,tree,commit,tag)
git对象的数据库管理方法
git cat-file -t sha1值:查看对象类型
git cat-file -p sha1值:查看对象内容
git cat-file -s sha1值:查看对象大小
git对象的类型
blob:二进制文件
git hash-object
:将文件写入数据库,在.git/objects生成二进制对象.
git cat-file -p sha1值 > 文件名
:恢复数据库文件至文件.
tree:某次commit对应的目录的快照
通常,Git 根据某一时刻暂存区(即 index 区域,下同)所表示的状态创建并记录一个对应的树对象, 如此重复便可依次记录(某个时间段内)一系列的树对象。
git write-tree
: 将暂存区内容写入一个树对象
对象格式打印如下:
040000 tree d564d0bc3dd917926892c55e3706cc116d5b165e dirTest(有非空子目录才有这一行)
100644 blob a29bdeb434d874c9b1d8969c40c42161b03fafdc test.txt
commit:每次commit成功,就会生成对应的commit对象。
对象格式打印如下:
tree 30da65dc22dabb8618043d58e14cf3d9b3473c41
parent cb293ac71cd34a7d81eba08cea0e9d3103588868 (首次commit没有这一行)
author 用户名 邮箱 1640156249 +0800
committer 用户名 邮箱 1640156249 +0800
commit信息
对象存储
https://git-scm.com/book/zh/v2/Git-%E5%86%85%E9%83%A8%E5%8E%9F%E7%90%86-Git-%E5%AF%B9%E8%B1%A1
tag:
标签对象通常指向一个提交对象,而不是一个树对象。 它像是一个永不移动的分支引用——永远指向同一个提交对象。
4) 文件的几种状态
未被跟踪的文件(untracked file)
已被跟踪的文件(tracked file)
被修改但未被暂存的文件(changed but not updated或modified)
已暂存可以被提交的文件(changes to be committed 或staged)
自上次提交以来,未修改的文件(clean 或 unmodified)
- 上层指令
git add
:只要文件发生变化,add之后,就会在.git/objects下生成新的sha1目录及文件。即使使用git rm --cached从暂存区移除文件甚至是git rm -f物理删除文件,.git/objects下的sha1目录及文件仍然存在,而且通过git cat-file -p 仍然可以查看文件内容。
git commit
:执行commit之后,会在.git/objects下本次commit对象及对应的tree对象.
git branch
:Git底层会运行 update-ref 命令,取得当前所在分支最新提交对应的 SHA-1 值,并将其加入你想要创建的任何新引用中。
- 底层指令
git hash-object
:将任意数据保存于 .git/objects 目录(即 对象数据库),并返回指向该数据对象的唯一的键.
git cat-file -t sha1值
:获取存储的对象类型
git cat-file -p sha1值
:查看二进制文件的内容。
Git底层原理
1.Git引用
HEAD引用、tag引用、远程引用
- HEAD引用
https://blog.csdn.net/albertsh/article/details/106448035(实践说明)https://segmentfault.com/a/1190000022506884
HEAD~与HEAD^的区别:https://www.cnblogs.com/mengff/p/12809911.html,如果某个commit有分叉(新建了分支),HEAD^N就会走第几个叉。
拓展
git采用的sha1算法,会产生哈希碰撞的风险吗?
会有碰撞的风险,但是风险系统极小,如火星撞地球的概率。一般git源代码平台都会有sha1哈希碰撞检测方法。
http://seanchense.github.io/2018/01/24/git-implementation-sha1-collision/
https://blog.csdn.net/weixin_33724046/article/details/90538691
sha1是不可逆的 为什么 git cat-file -p <sha1值> 能够还原文件内容?
根据file生成文件的sha1值, 而这个值基本上可以认定为是唯一的, 而且针对文件的每次修改, sha1值都是变化的。git系统中保存了sha1和file的对应关系, 所以可以直接拿sha1值得到具体的文件内容。
0 条评论