想晋级高级工程师只知道表面是不够的!Git内部原理介绍 (3)

$ git cat-file -p 0155eb4229851634a0f03eb265b69f5a2d56f341 100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt 100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt

此时发现,第一个树丢了,并没有跟第一个树有关系,通过 read-tree进行链接 $ git read-tree —prefix=bak d8329fc1cc938780ffdd9f94e0d364e0ea74f579

$ git write-tree 3c4e9cd789d88d8d89c1073707c3585e41b0e614

$ git cat-file -p 3c4e9cd789d88d8d89c1073707c3585e41b0e614 040000 tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579 bak 100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt 100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt

4.3.4 查看我们生成的树

img

4.4 提交对象引入

通过commit对象将这些树对象串起来。 创建第一个提交 $ echo ‘first commit’ | git commit-tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579 fdf4fc3344e67ab068f836878b6c4951e3b15f3d

创建第二个提交 $ echo ‘second commit’ | git commit-tree 0155eb -p fdf4fc3 cac0cab538b970a37ea1e769cbbde608743bc96d

创建第三个提交 $ echo ‘third commit’ | git commit-tree 3c4e9c -p cac0cab 1a410efbd13591db07496601ebc7a059dd55cfe9

版本库目录变化` **$ find .git/objects -type f** .git/objects/01/55eb4229851634a0f03eb265b69f5a2d56f341 # tree 2 .git/objects/1a/410efbd13591db07496601ebc7a059dd55cfe9 # commit 3 .git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a # test.txt v2 .git/objects/3c/4e9cd789d88d8d89c1073707c3585e41b0e614 # tree 3 .git/objects/83/baae61804e65cc73a7201a7252750c76066a30 # test.txt v1 .git/objects/ca/c0cab538b970a37ea1e769cbbde608743bc96d # commit 2 .git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4 # ‘test content’ .git/objects/d8/329fc1cc938780ffdd9f94e0d364e0ea74f579 # tree 1 .git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 # new.txt .git/objects/fd/f4fc3344e67ab068f836878b6c4951e3b15f3d # commit 1 `提交版本图

img

没有执行read-tree $ git log --stat 92387 commit 923879712b02f980a2edbe1cee315d883ee72503 Author: erweiwang <erweiwang@tencent.com> Date: Tue Jul 17 15:55:53 2018 +0800 second commit new.txt | 1 + test.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) commit e624badd39a25484a08ae74231be65ea50a0fe32 Author: erweiwang <erweiwang@tencent.com> Date: Tue Jul 17 15:54:20 2018 +0800 first commit test.txt | 1 + 1 file changed, 1 insertion(+) 五、包文件

Git 最初向磁盘中存储对象时所使用的格式被称为“松散(loose)”对象格式。 但是,Git 会时不时地将多个这些对象打包成一个称为“包文件(packfile)”的二进制文件,以节省空间和提高效率。 当版本库中有太多的松散对象,或者你手动执行 git gc 命令,或者你向远程服务器执行推送时,Git都会这样做。

git 打包对象时,会查找命名及大小相近的文件,并只保存文件不同版本之间的差异内容和文件最新版本的完整内容。

六、引用规格

引用规格的格式由一个可选的 + 号和紧随其后的 : 组成,其中 是一个模式(pattern),代表远程版本库中的引用; 是那些远程引用在本地所对应的位置。 + 号告诉 Git 即使在不能快进的情况下也要(强制)更新引用。

[remote "origin"] url = https://github.com/schacon/simplegit-progit fetch = +refs/heads/*:refs/remotes/origin/*

如果想让git每次只拉取远程master分支,而不是所有分支,可以将引用规格那一行修改为: fetch = +refs/heads/master:refs/remotes/origin/master

七、git clone代码库过程

执行git clone后,

拉取info/refs文件 => GET info/refs ca82a6dff817ec66f44342007202690a93763949 refs/heads/master

确定HEAD引用,明确检出至工作目录的内容 => GET HEAD ref: refs/heads/master 以上说明完成抓取后需要检出master分支

从info/refs文件中所提到的ca82a6提交对象开始 => GET objects/ca/82a6dff817ec66f44342007202690a93763949 (179 bytes of binary data)

根据ca82a6提取的的父提交对象和树对象开始遍历整个完整版本库。

在遍历过程中,若是未能直接找到(非松散对象)某些对象,会去替代版本库或某个包文件获取。

八、git推送远端库过程

为了上传数据至远端,Git 使用 send-pack 和 receive-pack 进程。 运行在客户端上的 send-pack 进程连接到远端运行的 receive-pack 进程。

九、扩展知识 9.1维护

git gc —auto //整理松散对象并放置包文件,将多个包文件合并为一个大的包文件,移除与任何提交不相关的陈旧对象

9.2数据恢复

确定需要恢复的版本 git reflog 查看git默默记录的每一次你改变的HEAD的值。 git log -g 可以详细的查看引用日志中各个版本的信息,风方便确定要恢复的提交。 如下所示 commit 1a410efbd13591db07496601ebc7a059dd55cfe9 Reflog: HEAD@{0} Reflog message: updating HEAD third commit commit ab1afef80fac8e34258ff41fc1b867c702daa24b Reflog: HEAD@{1} Reflog message: updating HEAD modified repo.rb a bit

创建用于恢复的临时分支

$ git branch recover-branch ab1afef

通过git fsck检查数据库的完整性(当reflog 也不存在需要恢复的版本)

当引用日志所在目录.git/logs/ 被不小心清空时

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpyggx.html