git的底层原理

对象 Objects

git使用 Object 存储所有类型的内容,也称为git对象,全部存储在 .git/objects/ 目录下

git使用40位的SHA-1值作为 object 文件的唯一标识符,前两位 SHA-1作为目录名称,后38位SHA-1作为文件名. git会把所有object进行zlib压缩.

object可以分为头部信息存储内容两部分

  • 头部信息: 类型+空格+内容字节数+\0
  • 存储内容

git有四种 object

  • Blob object 二进制对象
    • 对于普通文件,git使用 blob object (二进制对象) 存储文件内容.
  • Tree object 树对象
    • 对于目录文件,git使用一个 tree object (树对象) 存储一系列 tree entry, 每个 tree entry 存储一个 blob object (普通文件) 或一个 tree object (目录下的目录).
  • Commit object 提交对象
    • tree object和blob object用于表示版本快照,commit object用于表示版本索引和版本关系
    • commit object的存储内容包括:
      • 对应的根 tree object 对应的SHA-1
      • 0个,1个或多个父级commit object对应的SHA-1(第一次commit没有父节点,出现分支合并时会出现多个父级commit object)
      • commit的内容,包括:author,committer,encoding,commit message等
  • Tag object 标签对象

可以使用git cat-file 命令查看object的存储内容

1
2
3
git cat-file -t fa49b077972391ad58037050f2a75f74e3671e92  # 查看类型
git cat-file -s fa49b077972391ad58037050f2a75f74e3671e92 # 查看内容长度字节数
git cat-file -p fa49b077972391ad58037050f2a75f74e3671e92 # 查看内容

引用 refs

如果我们对某一个commit感兴趣,直接记忆SHA-1值并不方便,因此git提供了"别名"来代替SHA-1值,即 references (refs) 引用

git支持三种引用类型,存储在 .git/refs/

  • HEAD引用

    • 通常指向当前所在的分支(而并不是指向某一个commit对象)
    • 在特殊情况下(例如checkout一个commit导致detached head状态时),HEAD文件可能会包含一个git object的SHA-1值
    • 可以通过 cat .git/HEAD 查看HEAD文件
  • 标签引用 (tag reference)

    • 包含两种类型:轻量标签 和 附注标签

    • 轻量标签可以使用如下命令创建

      1
      git update-ref refs/tags/v1.0 a9f2652cb992f300c0a251d3607bdabfe8901bb2

      这条命令会创建一个以标签名命名的文本文件,文件内容位其所引用的commit object的SHA-1值

    • 附注标签可以使用如下命令创建

      1
      git tag -a v1.1 a9f2652cb992f300c0a251d3607bdabfe8901bb2 -m "test tag"

      这条命令会创建一个 tag object, 存储在 .git/objects/

      tag object的存储内容包括:所引用object的SHA-1值

  • 远程引用

    • 如果添加了远程仓库并执行过git push操作,git会记录最近一次push操作时每一个分支所对应的值,保存在 .git/refs/remotes/ 目录下

包文件 pack

每当我们对文件进行修改,git就会创建一个新的blob object(文件内容),如果文件很大,只修改其中的极小一部分内容,会导致严重的磁盘空间浪费。

git的解决方法是:不定时对blob对象打包并移除,生成两个文件

  • pack file (包文件): 采用原始内容+增量内容的形式存储
  • index file (索引文件): 存储各个pack file中object的大小/偏移/类型等数据,从而便于重建文件快照和object的关系

包文件存储在 .git/objects/pack/

可以使用 git verify-pack 查看

git push, git pull 等命令时git会自动进行打包,也可以手动使用 git gc 命令来进行打包

Commit

当执行 git commit 时,git会创建一个 commit object,包含指向顶层tree的指针,parent commit的哈希值,和作者/提交者信息/commit message等

工作区 索引 仓库

工作区即我们能看到和编辑的文件

索引(index, staging area) 是一个暂存区域,里面的代码会在下一次commit时被提交到git repo。当 git add xxx 时,该文件会被放在暂存区,同时新增一个 blob.

仓库 (git repository)即 .git 隐藏文件夹里的内容

分支

git分支,本质上只是一个指向commit对象的可变指针


git的底层原理
https://www.billhu.us/2026/068_git/
Author
Bill Hu
Posted on
April 26, 2026
Licensed under