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底层帮我们调用的,如果项目过大,我们也可以手动进行调用

相关推荐
Dontla2 小时前
脚本:git push直到成功(windows powershell命令)(Github连不上、Github断开)
git·github
CAE虚拟与现实2 小时前
GitHub Desktop 和 Git 命令行工具(CLI)各有优势
git·github·github desktop
RePeaT3 小时前
代码双仓库备份指南:三种简单高效的方法
git·github
xiezhr6 小时前
Git提交错了,别慌!还有后悔药
git·gitlab·github
GGGGGGGGGGGGGG.8 小时前
CI/CD 全链路实践:从 Git 基础到 Jenkins + GitLab 企业级部署
运维·git·ci/cd·云原生·gitlab·jenkins
叫我阿柒啊14 小时前
Java全栈开发面试实战:从基础到微服务架构
java·vue.js·spring boot·redis·git·full stack·interview
一只叫煤球的猫15 小时前
让版本控制变简单:Jujutsu (jj、git威力加强版) 使用手册
git·程序员·命令行
再难也得平19 小时前
如何在IDEA中使用Git
git
再难也得平19 小时前
Git分布式版本控制工具
git