Git GC

什么是 git gc

gc = Garbage Collection = 垃圾回收

git gc 用于整理 Git 仓库资源,减少仓库体积。

它的核心作用是将大量松散对象 (Loose Objects)压缩为pack 文件,从而提升存储和索引效率。

objects目录

Git 中的每个对象(包括 tree、blob、commit、tag)都会被序列化

  • 使用双向摘要算法生成唯一Hash值

然后为序列化后的内容,生成唯一SHA-1 哈希值(索引)

Git 对象包括:

  • blob:存储文件的内容

  • tree:存储目录结构

    • 一个tree对象表示当前目录和目录下的文件和子目录
    • 子目录又是另一个 tree对象对应的目录索引
    • 通过拼接这些对象,可以还原目录结构
  • commit:存储一次提交的信息(如作者、提交信息、指向的 tree 和父 commit 等)

  • tag:存储标签信息

.git/objects 目录下会有许多以两位十六进制命名的子目录。每个子目录中包含文件,这些文件的文件名是剩余的38位十六进制字符。子目录名和文件名拼接在一起,组成完整的 SHA-1 哈希值。

bash 复制代码
# 存在目录 02
cat 02 # 3b8b53a06506ea46dd954af6149697816cfcbf
# 则实际 SHA-1 是 023b8b53a06506ea46dd954af6149697816cfcbf 

refs 目录

.git/refs 目录用于存储 标签、分支等相关信息

进入 .git/refs 目录,可以看到三个重要子目录:

  • heads:本地分支
  • remotes:远程分支
  • tags:标签

heads(本地分支)

里面每个文件名对应一个本地分支

diff 复制代码
total 16
drwxr-xr-x@ 4 klaus  staff   128B  8 26 16:49 .
drwxr-xr-x@ 5 klaus  staff   160B  8 25 00:24 ..
-rw-r--r--@ 1 klaus  staff    41B  8 26 16:49 dev
-rw-r--r--@ 1 klaus  staff    41B  8 24 23:58 main

文件内容为该分支最新提交的 SHA-1 哈希值

bash 复制代码
cat main # 8a935ca1991f4e28c6d63e2fc8248e19a09cc452

remotes(远程分支)

目录下有远程仓库别名(如 origin)

kotlin 复制代码
total 0
drwxr-xr-x@ 3 klaus  staff    96B  8 25 00:24 .
drwxr-xr-x@ 5 klaus  staff   160B  8 25 00:24 ..
drwxr-xr-x@ 5 klaus  staff   160B  8 27 02:22 origin

仓库别名里面是远程分支名和 HEAD 文件

diff 复制代码
total 24
drwxr-xr-x@ 5 klaus  staff   160B  8 27 02:22 .
drwxr-xr-x@ 3 klaus  staff    96B  8 25 00:24 ..
-rw-r--r--@ 1 klaus  staff    41B  8 26 16:51 dev
-rw-r--r--@ 1 klaus  staff    30B  8 25 00:25 HEAD
-rw-r--r--@ 1 klaus  staff    41B  8 25 00:24 main

对应的文件内容如下

  • HEAD ⇒ 远程仓库主分支
  • 远程分支名 ⇒ 内容同样是 SHA-1 或引用
bash 复制代码
cat HEAD # ref: refs/remotes/origin/main
cat main # 8a935ca1991f4e28c6d63e2fc8248e19a09cc452

tags(标签)

进入 tags 目录,会发现每个标签对应一个文件

diff 复制代码
total 16
drwxr-xr-x@ 4 klaus  staff   128B  8 27 02:32 .
drwxr-xr-x@ 5 klaus  staff   160B  8 25 00:24 ..
-rw-r--r--@ 1 klaus  staff    41B  8 27 02:30 v1.0
-rw-r--r--@ 1 klaus  staff    41B  8 27 02:32 v1.1

对应的文件内容是

  1. 如果是轻量级标签 ⇒ 文件值是 最新提交ID

  2. 如果是带注释标签 ⇒ 文件值是 标签对象对应的SHA-1索引

    ⇒ 标签对象存在属性描述注释,也存在属性通过 SHA-1索引找到最新提交节点

执行 git gc 后发生了什么?

此时我们在项目工作目录执行 git gc

此时再依次查看 headsremotestags 会发现,除了remotes 还存在一个 origin/head

其余文件都消失了,其实他们都被压缩了

此时回到 .git 目录,查看后会发现多了一个目录 packed-refs ,这是一个压缩文件

如果此时我们执行 cat packed-refs

bash 复制代码
# pack-refs with: peeled fully-peeled sorted 
5e76ca292f3844a7a455ab9d11e3ee405e579171 refs/heads/dev
8a935ca1991f4e28c6d63e2fc8248e19a09cc452 refs/heads/main
5e76ca292f3844a7a455ab9d11e3ee405e579171 refs/remotes/origin/dev
8a935ca1991f4e28c6d63e2fc8248e19a09cc452 refs/remotes/origin/main
5e76ca292f3844a7a455ab9d11e3ee405e579171 refs/tags/v1.0
# 提交对象SHA-1 refs/tags/注释名
# ^带注释标签实际对应的提交对象的SHA-1索引
69cd0e5bfdec620cb878b19137ad52122ebf7b39 refs/tags/v1.1
^5e76ca292f3844a7a455ab9d11e3ee405e579171

这个文件里面包含了之前refs目录下的所有SHA-1值,相当于把分散的文件打包成一个压缩文件。

其实简单来说就是原本SHA-1索引存在于各个文件中,执行git gc 后被整合到一个文件中了

这样即减少了文件存储数量,也提高了索引效率

一般情况下, git gc 是 git底层帮我们调用的,如果项目过大,我们也可以手动进行调用

相关推荐
猫头虎35 分钟前
2026最新|GitHub 启用双因素身份验证 2FA 教程:TOTP.app 一键生成动态验证码(新手小白图文实操)
git·开源·gitlab·github·开源软件·开源协议·gitcode
爱学英语的程序员2 小时前
让AI 帮我做了个个人博客(附提示词!)
人工智能·git·vue·github·node·个人博客
liu****3 小时前
git工具
git·python·算法·机器学习·计算机基础
wxr06163 小时前
git无法克隆
git
cooldream20096 小时前
Git 拒绝推送(Push Rejected)问题全解析与解决方案实战指南
git
wxr06166 小时前
GIT无法push
git·gitee
装不满的克莱因瓶8 小时前
【踩坑】IDEA提交Git .gitignore忽略文件不起作用
java·git·.gitignore·踩坑
cos18 小时前
Fork 主题如何更新?基于 Ink 构建主题更新 CLI 工具
前端·javascript·git
OpenMiniServer19 小时前
当 AI 成为 Git 里的一个“人”
人工智能·git
Carry34520 小时前
不清楚的 .gitignore
前端·git