第1章:直接操纵对象
基础知识
Git对象放在<repo>/objects/中,分四种:
blob:文件内容,本质是前缀和文件原文
tree:文件夹内容,本质是经过zlib deflate处理的二进制数组,每个元素包括以下信息:
类型(文件夹040000,普通文件100644,可执行文件100755)
文件名
对应文件(blob)或者文件夹(tree)的SHA1
commit:本质是经过zlib deflate处理的以\n换行的纯文本,包括以下信息:
tree:代表根目录内容的tree的SHA1
parent(s):其他commit的SHA1
author:姓名、邮箱、秒时间戳、时区
committer:姓名、邮箱、秒时间戳、时区
mergetag(s):见第13章
gpgsig:见第13章
message:任意字节流
tag:本质是经过zlib deflate处理的以\n换行的纯文本,包括以下信息:
object:给谁做标记,可以是任意对象的SHA1
type:object的类型
tag:标记名称
tagger:姓名、邮箱、秒时间戳、时区
message:任意字节流
signature:见第13章
本章所有命令都不涉及worktree。后续章节会介绍如何利用worktree来操纵对象(Lv3)。
由于纯手工执行zlib deflate压缩、计算SHA1确实太麻烦,本章不介绍Lv0的对象创建方案, 只介绍Lv1的方案(即使用git hash-object来完成上述过程)。
创建blob
Lv1
Lv2
查看blob
Lv0
Lv2
Lv3
创建tree
Lv1
注意:要先对文件名排序,再使用
git hash-object
Lv2
注意:SHA1和文件名之间必须用tab分隔,在命令行里输入tab的方法是
<Ctrl-v><Tab>
查看tree
Lv0
Lv1
Lv2
使用
git ls-tree可以方便地看到文件夹的内容
Lv3
使用
git show直接作用在tree上可以看到简化版的文件夹内容
创建commit
Lv1
Lv2
查看commit
Lv0
Lv2
使用
git cat-tree可以方便地看到commit本身的内容
Lv3
使用
git show直接作用在commit上可以看到commit本身及其tree的diff情况
从commit找到tree和blob
Lv2
Lv3
创建tag
注意:你可以让tag指向tag,虽然没有什么卵用
Lv1 模仿commit的创建方法即可创建
Lv2
Lv3
特别注意:
git tag -a命令不仅仅创建了tag对象,还建立了新的引用在refs/tags/the-tag。
查看tag
Lv0 模仿commit的查看方法即可
Lv2
Lv3
检查文件系统
查找并删除无用对象:(有一定危险,可能会删掉有用的东西)
Lv2
检查文件系统完整性:
Lv2
“修改”对象
Git对象本身是无法修改的,但是Git提供了一种机制使得我们可以用一个新的对象来覆盖某个现成对象, 在访问原对象的时候会被自动定向到新的对象中。
若要将efd4替换为另外的一个commit,首先先创建一个commit:
添加replace
Lv0
Lv2
注意:若成环会导致错误
Lv3
无需提前创建,直接使用vim方便地修改对象:(此时要求新旧对象类型一致)
列出所有replace
Lv3
分别访问新旧对象
除非使用Lv0方式或者--no-replace-objects,否则访问efd4的时候总会被重定向到9f31:
Lv2
Lv3
取消replace,保留新旧两个对象
Lv0
Lv3
给对象添加备注
Git支持给任意对象添加备注,其本质是一个commit,其tree列出了备注内容blob和对应的对象SHA1(作为文件名)。 每个对象至多有一个备注。
添加备注
Lv1
Lv3
git notes edit会打开vim并编辑notes。
查看备注
Lv2
Lv3
删除备注
Lv1
Lv3
总结
Lv1
git hash-object -t <type> [--stdin|<file>] -w
Lv2
git mktree --missinggit commit-tree <tree> -m <message> [-p <parent>]*git mktaggit cat-file <type> <SHA1>git ls-tree <SHA1> -- [<path>]git count-objectsgit fsck [--unreachable] [--connectivity-only]git prune- 有一定危险,可能会删掉有用的东西git replace -f <original> <replacement>
Lv3
git tag -a -m <message> <name> <object>- 同时创建新引用在refs/tags/<name>git show <commit>git show <tree>- 如HEAD^{tree}git show <blob>- 如HEAD:index.jsgit replace --edit <original>git replace -l --format=longgit replace --delete <original>git notes add | list | show <object> | remove <object>
最后更新于
这有帮助吗?