底层命令与文件结构

Git 实质

参考

Git 是一个内容寻址文件系统。 这意味着,Git 的 核心部分是一个简单的键值对数据库。 你可以向该数据库插入任意类型的内容,它会返回一个键值,通过该键值可以在任意时刻再次检索(retrieve)该内容。


底层命令

涉及到的底层命令有:

命令 解释
cat-file 获取指定 Git 对象的信息
ls-files 显示暂存区的信息
ls-tree 显示指定结点的 tree 对象
hash-object 用于计算文件的 sha-1 值
update-index 更新暂存区
write-tree 将暂存区中的文件写成 tree 对象
read-tree 把树对象读入暂存区
commit-tree 根据指定的树对象创建一个提交对象
rev-parse 解析分支名或标签名对应的提交对象的 sha-1 值

Git 所做的实质工作 —— 将被改写的文件保存为数据对象(hash-object),更新暂存区 ( update-index ),记录树对象(write-tree),最后创建一个指明了顶层树对象和父提交的提交对象(commit-tree)。


ls-tree

用于显示指定结点对应的 tree 对象中的内容。

它会展示所有的文件(即 blob 对象)。

$ git ls-tree -r HEAD
100644 blob 34f7ae03cc475d78515719c5b6f8c34e46002f7f    aa
100644 blob c93ab02d540e388e1b83e23bbd8b49cb97c4b4ce    bb
100644 blob 837df2b7ed69104790e279524d51880324064492    cc
100644 blob 9b5cf45dcf51d69998fc7cdab86ea8afb2905047    cid.java
100644 blob 79f6e4824f9578f237633353e8d6939c8bffcca1    dd.txt
100644 blob 7f1021754129446ecef3fecab549015ccbe5e59f    ee
100644 blob f0e0aa843620d42bb1e72f4949001d0ca4173dc1    i/i.txt
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    i/ii/xx.txt
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    new
100644 blob 59f2c499c12c1385dd0ff1131a50820e7f6a618c    test.html
100644 blob d6459e005434a49a66a3ddec92279a86160ad71f    xxx.xxx

从输出可以看出,其中有几个文件是子目录下的文件,它也会直接列出来。


rev-parse

解析分支、标签等指向的提交对象的 sha-1 值。

如:

$     git rev-parse master
9b335a39f65dff232f239c08baeeb9f7d27f193a
$     git tag t1
$     git rev-parse t1
9b335a39f65dff232f239c08baeeb9f7d27f193a
$     git rev-parse HEAD
9b335a39f65dff232f239c08baeeb9f7d27f193a

master 与 HEAD 为分支名, t1 为标签名。


ls-files

用于获取暂存区的信息。

其常用的几个选项有:

-c : 在输出中显示暂存的文件。默认值。此选项只会输出文件名。

--stage : 显示文件的详细信息。包括文件名,sha-1 值,文件模式等。

$ git ls-files --stage
100644 6b20baa0a072d5c9578e024942c6ce1d42cf5a2a  0          a.txt
100644 24e27b2a30edadba619d26e2d3662ec307cdddb2 0   test.html
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0   xx

上述命令显示当前暂存区中暂存的有三个文件。


hash-object 命令

计算文件的 sha-1 值,并可选地根据该文件创建一个 blob 对象。

注意:该命令只适用于文件,不能用于目录

选项 解释
-w 不加该选项则不会生成 blob 对象,反之则会生成
--stdin hash-object 命令会从标准输入读取内容
-- <path> 指定 hash-object 操作的文件的路径

注意:如果使用 --stdin 选项,就需要指定文件路径。

如:

$ find .git/objects/ -type f
$ git hash-object -- ../appid.txt 
a5a06de3b66ee3a609def184e78873c99d6b1221
$ find .git/objects/ -type f
$ git hash-object -w -- ../appid.txt 
a5a06de3b66ee3a609def184e78873c99d6b1221
$ find .git/objects/ -type f
.git/objects//a5/a06de3b66ee3a609def184e78873c99d6b1221

find 命令用于查找指定目录( .git/objects )目录下的所有文件( 通过 -type f 限定 )。

从上可以看出,起初 objects 目录下并没有文件。hash-object 不加 -w 操作后,目录下依旧没有文件,只不过输出了指定文件的 sha-1 值。

加上 -w 选项后,objects 目录下多了一个父目录为 a5 的文件。Git 会截取 sha-1 值的前两个字符生成目录名,将剩余的部分做为文件名。因此,objects 目录下会有一个 a5 目录。


cat-file

获取指定的 Git 对象的内容等信息。

其常用的选项如下:

选项 解释
-p 后跟 sha-1 值,则 cat-file 会返回该 sha-1 值的内容
-t 获取指定对象的类型
-s 获取指定对象的大小

在使用时,可以通过 > <path> 后缀,将 cat-file 的输出内容输出到指定的文件中。如 git cat-file -p bf43b62de7d99fa2c427dcc82257d81431ba816f > xxx.xxx 就会将内容输出到同目录下的 xxx.xxx 文件中。

如 -p 选项的使用:

$ git cat-file -p 9daeafb9864cf43055ae93beb0afd6c7d144bfa4
test

其中 test 为该对象的内容。

如 -t 选项的使用:

$ git cat-file -t ee1a8365ec2baa3e5a97cb6e44d8d8b5c553fb30
blob

$ git cat-file -t 8bdb01d84c5ad6456acb4d8df8d82a0db5214972
tree

$ git cat-file -t bf43b62de7d99fa2c427dcc82257d81431ba816f
commit

Git 中一共有三种对象 :commit , tree 与 blob ,所以 -t 只会输出这三个值中的一个。


update-index

该选项用于更新暂存区。git addgit rm 等命令都是对该选项的封装。

其常用的选项有:

选项 解释
<无> 更新已暂存的文件
--add 将未跟踪的文件添加到暂存区中
--cacheinfo 将已保存到本地仓库的文件加入到暂存区中
--remove 将已删除的文件从暂存区中移除

各个选项具体说明如下:

  1. --add : 如果文件从来没有添加到暂存区中,该选项表示将文件第一次添加到暂存区中

    $ git ls-files --stag
    100644 6b20baa0a072d5c9578e024942c6ce1d42cf5a2a 0   a.txt
    
    $ git hash-object yy
    e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
    $ git update-index --add yy
    $ git ls-files --stage
    100644 6b20baa0a072d5c9578e024942c6ce1d42cf5a2a 0   a.txt
    100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0   yy
    

    初始时,暂存区中只有一个 a.txt 文件。使用 git update-index --add 命令后,暂存区中多了一个 yy 文件,并且 yy 文件与 update-index 指定的文件的 sha-1 值相同,所以该命令可以将指定的文件添加到暂存区中。

    再查看 .git/objects 目录下,可以发现多了一个文件(即 yy 文件)。

  2. --cacheinfo:如果要保存的文件已位于 git 仓库中,需要使用该选项。

    $ vim yy 
    $ git hash-object -w -- yy 
    9be86ae7054f7c477afabe3d971046032851b574
    
    $ git update-index --cacheinfo 100644 9be86ae7054f7c477afabe3d971046032851b574 yy 
    

    首先修改 yy 文件,并通过 hash-object 将文件存储到 git 目录中。所以更新暂存区时不需要 --add 选项。

    在使用 --cacheinfo 修改暂存区时,指定了文件的 sha-1 值,同时也指定了文件模式为 100644(即普通文件)。

  3. --remove:将指定的文件从索引中删除,该文件必须已经从工作目录中删除

    $ git ls-files --stage
    100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0   xx
    100644 9be86ae7054f7c477afabe3d971046032851b574 0   yy
    
    $ rm xx 
    $ git update-index --remove -- xx
    $ git ls-files --stage
    100644 9be86ae7054f7c477afabe3d971046032851b574 0   yy
    
    $ git update-index --remove -- yy 
    $ git ls-files --stage
    100644 9be86ae7054f7c477afabe3d971046032851b574 0   yy
    

    不删除文件直接使用 --remove 选项时,并不会删除相应的记录(如上例中的 yy 文件)。


write-tree

将暂存区内容写入一个树对象。

通过 update-index 更新暂存区后,基本的文件并没有生成成 tree 对象。而 write-tree 可以根据暂存区生成一个树对象。

$ git write-tree
348eb10c8ce3e5a4561a38aa7e76e61013e153e1

$ git cat-file -t 348eb10c8ce3e5a4561a38aa7e76e61013e153e1
tree

read-tree

将指定的树对象读入到暂存区中。

通过 --prefix=name 指定读入的树对象的名字。

首先将一个树对象读入暂存区中,然后通过 write-tree 将暂存区中的内容写入一个树对象中。则新生成的树对象会包含一个指向通过 read-tree 读入的树对象的指针。

$ git read-tree --prefix=namep 348eb10c8ce3e5a4561a38aa7e76e61013e153e1

执行上述命令后,如果将当前暂存区生成一个 tree 对象后,该对象会包含一个名为 namep 的指针,它指向的是通过 read-tree 读入的树对象。


commit-tree

根据指定的树对象创建一个提交对象。

通过 -p sha-1 指定当前对象的父对象

$ echo "first commit" | git commit-tree 2aabf73883cc35cef05f3c7919274da2aaebf674
cbc41af8ae9347c21299005f40ce998e58ab357e

$ echo "third" | git commit-tree fa197580163fc711a76726db35488f433968699c -p cbc41af8ae9347c21299005f40ce998e58ab357e

7e0792c1e2b634b4721edc6e3ff6f206d18298a2

echo 指定的是本次提交的说明。

上述命令新建了两个 commit 对象,并将第二个 commit 对象的父结点指向第一个对象。

当在第二个 commit 对象处建立分支后,运行 git log 命令,可以发现有两条提交记录。


目录

Git 有几个非常重要的文件:

  1. objects 目录存储所有数据内容;

  2. refs 目录存储指向数据(分支)的提交对象的指针。

    1. refs/heads 存储的是当前的是各个分支,每一个文件记录了该分支最后一个提交结点的 sha-1 值。

    2. refs/tags 目录下记录的是各个标签。

    3. refs/remotes 存储当前仓库配置的远程服务器。其每一个子目录就对应着一个远程仓库 —— 子目录名字就是通过 git remote add <别名> url 中的别名。子目录下的各个文件指的是远程仓库的各个分支。

  3. HEAD 文件指示目前被检出的分支;

  4. index 文件保存暂存区信息。

  5. config 文件保存 --local 的配置信息。例如我们使用 git remote add <别名> url 命令时,会在 config 文件中添加如下信息。其具体信息可参考 remote一节:

    [remote "demo"]
        url = https://github.com/birdandcliff/gitdemo.git
        fetch = +refs/heads/re:refs/remotes/demo/devlocal
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容

  • Git 基础 基本原理 客户端并不是只提取最新版本的文件快照,而是把代码仓库完整的镜像下来。这样一来,任何一处协同...
    __silhouette阅读 15,883评论 5 147
  • 以下笔记主要参考gitgot,大致了解git使用和原理。 第一部分我们从个人的视角去研究如何用好Git,并且揭示G...
    carolwhite阅读 2,379评论 0 1
  • 这本书已经读完了一段时间,可是迟迟不敢动笔写,怕自己写不出文里的精髓。 再次打开这本书是在去西安的高铁上,也许正好...
    白水若千阅读 153评论 0 1
  • 成都真是一座温柔的城市。只在夜里下雨。没有那么多赤裸裸的晴朗,仿佛就是不想叫你参透人生,然后在你最绝望的时候,来一...
    迷鹿少女LuC阅读 1,579评论 1 8
  • 一:web.xml加载过程简单说一下,web.xml的加载过程。当我们启动一个WEB项目容器时,容器包括(JBos...
    把爱放下会走更远阅读 3,642评论 0 6