Skip to content

Git暂存区是如何工作的 #2

@Phieo

Description

@Phieo

Git暂存区是如何工作的

说到Git,肯定要说到下面图中的几个概念:工作目录、暂存区以及HEAD。

basic

一次改动进行git add后,就会将这次改动存放到暂存区。下面要具体讲一下存放暂存区的具体细节。

.git/index

index其实是用来记录每次改动的提交的,它是二进制文件,可以使用如下方式打开查看:

$ echo 'hello world' > a
$ git add .
$ hexdump .git/index

0000000 44 49 52 43 00 00 00 02 00 00 00 01 5a c2 21 c0
0000010 2d 21 ac 51 5a c2 21 c0 2d 21 ac 51 01 00 00 04
0000020 00 76 65 5b 00 00 81 a4 00 00 01 f5 00 00 00 14
0000030 00 00 00 0c 3b 18 e5 12 db a7 9e 4c 83 00 dd 08
0000040 ae b3 7f 8e 72 8b 8d ad 00 01 61 00 95 7a 86 ac
0000050 65 d8 a8 db 44 fd e7 37 56 b3 1b bd 43 30 5c b2
0000060

而且可以观察到index文件只有在第一次进行git add后才存在。

那这一串十六进制数代表什么意思呢?

Git是对文件内容的管理

Git追踪的是内容而不是文件,这意味着你每次改动项目,git都会将这次改动记录下来,而存储改动的方式就是用key-value的方式,而这个key就是存储在index文件中,即上面提到的那串十六进制数。

.git/objects

刚刚说了每次改动的key是存在index文件中,那么value就存在objects文件中,在刚才目录下进行以下操作:

$ tree .git/objects

.git/objects
├── 3b
│   └── 18e512dba79e4c8300dd08aeb37f8e728b8dad
├── info
└── pack

可以发现的是3b18e512dba79e4c8300dd08aeb37f8e728b8dad这串十六进制数在.git/index文件中是存在的,这样key-value的关系就对应起来了。这串数字就是Git对object执行了一些操作,计算得出的SHA1散列值。

index文件包含哪些信息

刚才提到的index文件包含了每次改动的key。具体还包含哪些呢?看这里index-format.txt

objects包含哪些信息

对应关系找到了,那具体存储内容是什么呢?用以下指令进行操作:

$ git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad
hello world

关于git cat-file是干嘛用的,可以查看git-cat-file

objects的类型分四类:

  • blob
  • tree
  • commit
  • tag

进行下列操作:

$ echo 'hi' >> a
$ git add .
$ git commit -m 'initial commit'
$ tree .git/objects
.git/objects
├── 2d
│   └── e63a9cb36fffd59f81acb4fa3612ccbcaf74af
├── 3b
│   └── 18e512dba79e4c8300dd08aeb37f8e728b8dad
├── 9e
│   └── 26b6c4891f86977a64326ecbf9a3eb93c73654
├── a4
│   └── 6c9e1cbdefdb3ca2eca76bb175e31eebbe5d50
├── info
└── pack
$ git cat-file -t 2de63a9cb36fffd59f81acb4fa3612ccbcaf74af

blob

$ git cat-file -p 2de63a9cb36fffd59f81acb4fa3612ccbcaf74af
hello world
hi

可以看到Git有效的存储了每个文件的的每个版本,而不是它们的差异。每次执行git add时,每个文件的全部内容都会被复制到对象库中,并且按文件的SHA1命来索引。

$ git cat-file -t 9e26b6c4891f86977a64326ecbf9a3eb93c73654
tree

git cat-file -p 9e26b6c4891f86977a64326ecbf9a3eb93c73654
100644 blob 2de63a9cb36fffd59f81acb4fa3612ccbcaf74af	a
$ git cat-file -t a46c9e1cbdefdb3ca2eca76bb175e31eebbe5d50
commit

git cat-file -p a46c9e1cbdefdb3ca2eca76bb175e31eebbe5d50
tree 9e26b6c4891f86977a64326ecbf9a3eb93c73654
author xx <xx@xx.com> 1522672548 +0800
committer xx <xx@xx.com> 1522672548 +0800

initial commit

每次完整的提交都是会包含每次add的快照、工作目录以及commit。Git就是通过commit、tree以及blob对文件内容进行追踪。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions