您的位置:首页 > 其它

《Git权威指南》读书笔记 第六章 Git对象

2016-07-17 00:00 204 查看
摘要: 本章介绍了Git对象库中的主要对象类型,它们的HASH值得计算方法、使用HASH作为提交ID的原因以及一些方访问it对象的技巧。

6.1 Git对象库

一次提交有三个拥有哈希值的对象:

本次提交;

本次提交所对应的目录树;

贝蒂提交的父提交(上一次提交)。

git log --pretty=format:" "

format中的%H输出本次提交的哈希值;%T输出本次提交对应目录树的哈希值;%P输出父提交的哈希值。

查看哈希值的类型:

$ git log --pretty=format:"%H"
326f2370369566e4cacc4c149e612adaba378716
32d79d5cf6e6eac8c95b7978588e4f9db3139a45
4f804c3948640ce146e48f0ff7c4d4592693df87

$ git cat-file -t 326f23
commit

查看哈希值对应commit对象的详细信息:

$ git cat-file -p 326f23
tree 76e015495ba4151ac95340f948778d78fa18bb8f
parent 32d79d5cf6e6eac8c95b7978588e4f9db3139a45
author jiangzhi <ivanjz93@163.com> 1468591788 +0800
committer jiangzhi <ivanjz93@163.com> 1468591788 +0800

which version checked in?

查看哈希值对应tree对象的详细信息:

$ git cat-file -p 76e015
100644 blob b0e5c6e24bc84d489773b2fda5accf005bc912f1    welcome.txt

目录树对象中看到了一个新类型的对象:blob对象,这个对象保存着文件welcome.txt的内容:

$ git cat-file -p b0e5c6
Hello
Nice to meet you.

上面介绍的这些对象都保存在Git库中的objects目录下面(ID的前两位作为目录名,后38位作为文件名)。使用下面命令查看这些对象在对象库中的实际位置:

$ for id in 76e015 32d79d 4f804c b0e5c; do ls .git/objects/${id:0:2}/${id:2}*;done
.git/objects/76/e015495ba4151ac95340f948778d78fa18bb8f
.git/objects/32/d79d5cf6e6eac8c95b7978588e4f9db3139a45
.git/objects/4f/804c3948640ce146e48f0ff7c4d4592693df87
.git/objects/b0/e5c6e24bc84d489773b2fda5accf005bc912f1

可以查看提交对象之间的相互关联:

$ git log --pretty=raw --graph 326f23
* commit 326f2370369566e4cacc4c149e612adaba378716
| tree 76e015495ba4151ac95340f948778d78fa18bb8f
| parent 32d79d5cf6e6eac8c95b7978588e4f9db3139a45
| author jiangzhi <ivanjz93@163.com> 1468591788 +0800
| committer jiangzhi <ivanjz93@163.com> 1468591788 +0800
|
|     which version checked in?
|
* commit 32d79d5cf6e6eac8c95b7978588e4f9db3139a45
| tree 1bd6c8f9223ed7d5f8e74af92c561398011ede77
| parent 4f804c3948640ce146e48f0ff7c4d4592693df87
| author jiangzhi <ivanjz93@163.com> 1468585955 +0800
| committer jiangzhi <ivanjz93@163.com> 1468585955 +0800
|
|     who does commit?
|
* commit 4f804c3948640ce146e48f0ff7c4d4592693df87
tree 1bd6c8f9223ed7d5f8e74af92c561398011ede77
author ivanjz93 <ivanjz93@163.com> 1468379590 +0800
committer ivanjz93 <ivanjz93@163.com> 1468379590 +0800

initialized.

使用:

git status -s -b
## master

查看当前工作区的状态精简信息和当前工作分支的名称(-b参数)。

使用下面的命令查看当前的工作分支:

git branch
* master

master前面的*表示这个分支是当前工作分支。git branch命令时分支管理的主要命令。

使用下面三个命令会得到相同的输出:

git log -l HEAD
git log -l master
git log -l refs/heads/master

也就是说在当前版本库中,HEAD、master和refs/heads/master具有相同的指向。

查看.git/HEAD文件的内容:

$ cat .git/HEAD
ref: refs/heads/master

它指向了.git/refs/heads/master。

查看这个文件的内容:

$ cat .git/refs/heads/master
326f2370369566e4cacc4c149e612adaba378716

得到一个哈希值,查看这个哈希值的类型和内容:

$ git cat-file -t 326f23
commit

$ git cat-file -p 326f23 tree 76e015495ba4151ac95340f948778d78fa18bb8f parent 32d79d5cf6e6eac8c95b7978588e4f9db3139a45 author jiangzhi <ivanjz93@163.com> 1468591788 +0800 committer jiangzhi <ivanjz93@163.com> 1468591788 +0800 which version checked in?

分支master指向的是一个提交ID(最新提交)。可以从.git/refs/heads/master这个文件追踪整个提交历史。

目录.git/refs是保存引用的命名空间,其中.git/refs/heads目录下的引用又称为分支。对于分支,既可以用正规的长格式的表示法,如refs/heads/master,也可以直接用master表示。Git有一个命令git rev-parse可以用于显示引用对应的提交ID:

$ git rev-parse HEAD
326f2370369566e4cacc4c149e612adaba378716

$ git rev-parse refs/heads/master
326f2370369566e4cacc4c149e612adaba378716

$ git rev-parse master
326f2370369566e4cacc4c149e612adaba378716

6.2 SHA1哈希值

1、提交的SHA1哈希值生成方法

(1)首先查看HEAD对应的提交内容:

$ git cat-file commit HEAD
tree 76e015495ba4151ac95340f948778d78fa18bb8f
parent 32d79d5cf6e6eac8c95b7978588e4f9db3139a45
author jiangzhi <ivanjz93@163.com> 1468591788 +0800
committer jiangzhi <ivanjz93@163.com> 1468591788 +0800

which version checked in?

(2)提交信息中总共包含228个字符:

$ git cat-file commit HEAD | wc -c
228

(3)在提交的信息前面加上commit 228<null>,然后执行SHA1哈希算法:

$ (printf "commit 228\000"; git cat-file commit HEAD) | sha1sum
326f2370369566e4cacc4c149e612adaba378716 *-

(4)计算得到的哈希值与用git rev-parse HEAD得到的相同:

$ git rev-parse HEAD
326f2370369566e4cacc4c149e612adaba378716

2、文件内容的SHA1哈希值生成方法

(1)查看版本库中welcome.txt的内容:

$ git cat-file blob HEAD:welcome.txt
Hello
Nice to meet you.

(2)文件总共包含25个字节的内容:

$ git cat-file blob HEAD:welcome.txt | wc -c
25

(3)在文件内容前面加上blob 25<null>的内容,然后执行SHA1哈希算法:

$ (printf "blob 25\000"; git cat-file blob HEAD:welcome.txt) | sha1sum
b0e5c6e24bc84d489773b2fda5accf005bc912f1 *-

(4)计算得到的哈希值与文件的哈希值相同:

$ git rev-parse HEAD:welcome.txt
b0e5c6e24bc84d489773b2fda5accf005bc912f1

3、树的SHA1哈希值计算方法

(1)HEAD对应的树的内容包含39个字节:

$ git cat-file tree HEAD^{tree} | wc -c
39

(2)在树的内容前面加上tree 39<null>,然后执行SHA1哈希算法:

$ (printf "tree 39\000";git cat-file tree HEAD^{tree}) |sha1sum
76e015495ba4151ac95340f948778d78fa18bb8f *-

(3)与树的哈希值一致:

$ git rev-parse HEAD^{tree}
76e015495ba4151ac95340f948778d78fa18bb8f

6.3 不使用顺序的数字表示提交

Git不像SVN那样使用顺序递增的数字表示提交。因为集中式版本控制系统只有一个集中式的版本库,所以可以很容易的实现依次递增的全局唯一的提交号。Git作为分布式版本控制系统,开发可以是非线性的,每个人都可以通过克隆版本库的方式工作在不同的本地版本库当中,在本地做的提交可以通过版本局之间的交互(推送和拉回操作)而相互分发,如果提交采用本地唯一的数字编号,在提交分发的时候会出现冲突。这就要求提交的编号是全球唯一的。

SHA1哈希值使得提交编号变得复杂,因此Git提供了很多方法可以方便的访问Git库中的对象:

使用哈希值时可以只写部分,而不必把40位的哈希值写全,只采用开头的部分,只要不与现有的其他哈希值冲突即可;

使用master代表分支master中最新的提交,也可以使用全称refs/heads/master或/heads/master;

使用HEAD代表版本库中最近的一次提交;

符号^可以用于指代父提交,例如:HEAD^代表版本库中的上一次提交,HEAD^^代表HEAD^的父提交;

对于一个提交有多个父提交的情况,可以在符号后面用数字表示第几个父提交,例如:a573106^2表示这个提交的第二个父提交,HEAD^^2表示HEAD^的第二个父提交;(这个地方表述的不清楚,是只祖父提交,还是一个提交有多个父亲?)

符号~<n>用于指代祖父提交,例如a573106~5相当于a573106^^^^^;

提交所对应的树对象,可以用a573106^{tree}表示;

某一次提交对应的文件对象,可以用a573601:path/to/file访问;

暂存区中的文件对象,可以用:path/tp/file访问。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息