Re-visit Git
Git中文件状态
有三种:已提交(committed)、已修改(modified) 和 已暂存(staged)。
Modified/Not staged: 表示修改了文件,但还没保存到数据库中。
Staged: 表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
Committed: 表示数据已经安全地保存在本地数据库中
Git内部原理
git init
当在一个新目录或已有目录执行 git init 时,Git 会创建一个 .git 目录。 这个目录包含了几乎所有 Git 存储和操作的东西。 如若想备份或复制一个版本库,只需把这个目录拷贝至另一处即可。 本章探讨的所有内容,均位于这个目录内。 新初始化的 .git 目录的典型结构如下:
$ ls -F1
config # 包含项目特有的配置选项
description # 仅供 GitWeb 程序使用
HEAD
hooks/ # 包含客户端或服务端的钩子脚本
info/ # 包含一个全局性排除(global exclude)文件, 用以放置那些不希望被记录在 .gitignore 文件中的忽略模式(ignored patterns)
objects/
refs/
剩下的四个条目很重要, 它们都是 Git 的核心组成部分:
HEAD
文件: 指向目前被检出的分支。- (尚待创建的)
index文件
: 保存暂存区信息。 objects目录
: 存储所有数据内容。refs目录
: 存储指向数据(分支、远程仓库和标签等)的提交对象的指针。
git object
数据对象(blob)和树对象(tree object): Git 以一种类似于 UNIX 文件系统的方式存储内容,但作了些许简化。 所有内容均以树对象和数据对象的形式存储,其中树对象对应了UNIX中的目录项,数据对象则大致上对应了inodes
或文件内容。 一个树对象包含了一条或多条树对象记录(tree entry),每条记录含有一个指向数据对象或者子树对象的 SHA-1 指针,以及相应的模式、类型、文件名信息。
Git的核心部分是一个简单的键值对数据库(key-value data store),与此相关的命令:
git hash-object
: 该命令可将任意数据保存于 .git/objects 目录(对象数据库),并返回指向该数据对象的唯一的键。git cat-file
: 从Git那里取回数据。
# -w 选项会指示该命令不要只返回键,还要将该对象写入数据库中
# -stdin 选项则指示该命令从标准输入读取内容, 若不指定此选项,则须在命令尾部给出待存储文件的路径。
$ echo 'test content' | git hash-object -w --stdin
d670460b4b4aece5915caf5c68d12f560a9fe3e4
$ find .git/objects -type f
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
# -p 选项可指示该命令自动判断内容的类型,并为我们显示大致的内容
$ git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4
test content
有一个问题是,在这个简单的版本控制系统中,文件名并没有被保存 —— 我们仅保存了文件的内容。 上述类型的对象我们称之为数据对象(blob object)。 利用git cat-file -t
命令,可以让 Git 告诉我们其内部存储的任何对象类型,只要给定该对象的 SHA-1 值: