第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 --missing

    • git commit-tree <tree> -m <message> [-p <parent>]*

    • git mktag

    • git cat-file <type> <SHA1>

    • git ls-tree <SHA1> -- [<path>]

    • git count-objects

    • git 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.js

    • git replace --edit <original>

    • git replace -l --format=long

    • git replace --delete <original>

    • git notes add | list | show <object> | remove <object>

最后更新于

这有帮助吗?