01 Object

[ Mac-mini:/Users/lijuzhang/test ] ➜ mkdir git-demo
[ Mac-mini:/Users/lijuzhang/test ] ➜ cd git-demo
[ locolhost:/Users/lijuzhang/test/git-demo ] ➜ git init .
Initialized empty Git repository in /Users/lijuzhang/test/git-demo/.git/
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ ls -a
. .. .git
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ ls -la .git
total 24
drwxr-xr-x 9 lijuzhang staff 288 4 9 11:19 .
drwxr-xr-x 3 lijuzhang staff 96 4 9 11:19 ..
-rw-r--r-- 1 lijuzhang staff 23 4 9 11:19 HEAD
-rw-r--r-- 1 lijuzhang staff 137 4 9 11:19 config
-rw-r--r-- 1 lijuzhang staff 73 4 9 11:19 description
drwxr-xr-x 13 lijuzhang staff 416 4 9 11:19 hooks
drwxr-xr-x 3 lijuzhang staff 96 4 9 11:19 info
drwxr-xr-x 4 lijuzhang staff 128 4 9 11:19 objects
drwxr-xr-x 4 lijuzhang staff 128 4 9 11:19 refs
我们发现,init后,会在当前目录下生成一个.git目录。该目录下有很多的文件。
.git目录下文件详解
config:当前仓库的本地配置文件。除此之外,git还有一个全局的配置文件:
~/.gitconfig,此外全局的配置文件可以通过git config --global --list查看。# 查看全局配置文件 [ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ cat ~/.gitconfig [core] quotepath = false excludefile = /Users/lijuzhang/.gitignore_global [user] name = lijuzhang email = lijuzhang@inspur.com # 查看全局配置 [ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git config --global --list core.quotepath=false core.excludefile=/Users/lijuzhang/.gitignore_global user.name=lijuzhang user.email=lijuzhang@inspur.com (END) # 修改/查看配置项: git config [--global] [ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git config --list [ locolhost:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git config user.name ljzsdut [ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true [user] name = ljzsdut [ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git config --get user.name ljzsdut
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ tree .git
.git
├── HEAD
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ └── update.sample
├── info
│ └── exclude
├── objects
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
8 directories, 15 files
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ echo 'hello git' >git.txt
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ git add git.txt
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ tree .git
.git
├── HEAD
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ └── update.sample
├── index #新生成的文件1
├── info
│ └── exclude
├── objects #(命名使用sha-1类型的hash值,对文件内容、对象类型、内容长度等信息的组合进行hash计算)
│ ├── 8d #新生成的目录(文件名hash值的前2位)
│ │ └── 0e41234f24b6da002d962a26c2495ea16a425f #新生成的文件2(文件名hash值的第3位开始)
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
9 directories, 17 files #多了1个目录和2个文件。
git add命令执行后,会多了1个目录和2个文件。
我们前面提到,object的hash值是对文件内容、对象类型、内容长度等信息的组合进行sha1 hash计算。具体进行hash的内容为对象type 文本长度\0文件内容,即对象的类型(取值blob, tree, commit, tag)、空格、文本的长度(单位Byte)、文件内容。
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ echo "blob $(wc -c git.txt |awk '{print $1}')\0$(cat git.txt)"
blob 10hello git
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ echo "blob $(wc -c git.txt |awk '{print $1}')\0$(cat git.txt)" |sha1sum
8d0e41234f24b6da002d962a26c2495ea16a425f -
说明:sha1 hash可能会发生hash碰撞,一旦发生hash碰撞,后面添加的文件内容会被第1个文件的内容覆盖。官方计划将sha1升级为sha256。
我们已经知道,一个对象包含了:对象类型、对象大小、对象内容。我们可以通过cat-file子命令查询对象的以上信息。
# 查看对象的类型type
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ git cat-file -t 8d0e41
blob
# 查看object的内容content
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ git cat-file -p 8d0e41
hello git
# 查看对象大小
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ git cat-file -s 8d0e41
10
object里存储了哪些内容:
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ cat .git/objects/8d/0e41234f24b6da002d962a26c2495ea16a425f
xK��OR04`�H���WH�,�6A�%
上面的乱码,是原始内容压缩后的二进制格式的内容,我们可以解压缩:
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ python3
Python 3.9.7 (default, Sep 3 2021, 12:45:31)
[Clang 12.0.0 (clang-1200.0.32.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import zlib
>>> c = open('.git/objects/8d/0e41234f24b6da002d962a26c2495ea16a425f','rb').read()
>>> zlib.decompress(c)
b'blob 10\x00hello git\n'
可见,object只存储文件的内容、大小、对象类型,而不存储文件的名字。可以使用如下方式验证:
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ echo 'hello git' >tmp.txt
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ git add tmp.txt
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ tree .git
.git
├── HEAD
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── objects
│ ├── 8d
│ │ └── 0e41234f24b6da002d962a26c2495ea16a425f
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
9 directories, 17 files #发现文件数量没有发生任何的变化
其实文件名是存储在index文件中的,该文件中记录了所有位于index区域的文件。
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ cat .git/index
DIRCbP��d$obP��d$ob����
�A#O$��-�*&�I^�jB_git.txtbQ�|bQ�|g����
�A#O$��-�*&�I^�jB_tmp.txtV諞�_��l����^%
看见,index里存储的也是二进制格式,可以使用ls-files子命令进行查看:
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ git ls-files
git.txt
tmp.txt
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ git ls-files -s
100644 8d0e41234f24b6da002d962a26c2495ea16a425f 0 git.txt
100644 8d0e41234f24b6da002d962a26c2495ea16a425f 0 tmp.txt
# 权限 blob对象 文件名
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ cat git.txt
hello git
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ echo 1 >>git.txt
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ git add git.txt
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ tree .git
.git
├── HEAD
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── objects
│ ├── 50
│ │ └── 0403283f5ed39ff656d0acfaf7ce4ec22494dd #修改后,新生成的
│ ├── 8d
│ │ └── 0e41234f24b6da002d962a26c2495ea16a425f #修改前
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
10 directories, 18 files
[ locolhost:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ git cat-file -p 8d0e
hello git
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ git cat-file -p 5004
hello git
1
可以发现,修改文件并执行git add后,修改之前的对象依旧存在,没有被删除。这是因为对象是可以被复用的,可能多个文件引用一个对象。即便是没有文件的对象,也不会立即被删除,这些对象称之为是垃圾对象。
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ tree .git
.git
├── HEAD
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── objects
│ ├── 50
│ │ └── 0403283f5ed39ff656d0acfaf7ce4ec22494dd
│ ├── 8d
│ │ └── 0e41234f24b6da002d962a26c2495ea16a425f
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
10 directories, 18 files
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ git commit -m "1st commit"
[master (root-commit) 3cb18e8] 1st commit
2 files changed, 3 insertions(+)
create mode 100644 git.txt
create mode 100644 tmp.txt
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ tree .git
.git
├── COMMIT_EDITMSG #file
├── HEAD
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs #
│ ├── HEAD #f
│ └── refs #
│ └── heads #
│ └── master #f
├── objects
│ ├── 3c
│ │ └── b18e8893083b917ab79b34afa7bca9e3cfd426 #commit_id
│ ├── 50
│ │ └── 0403283f5ed39ff656d0acfaf7ce4ec22494dd
│ ├── 5c
│ │ └── 6781b18b7c61773120fca8b5006fb9cba71e49 #tree类型
│ ├── 8d
│ │ └── 0e41234f24b6da002d962a26c2495ea16a425f
│ ├── info
│ └── pack
└── refs
├── heads
│ └── master #f
└── tags
15 directories, 24 files
多了2个object:
# 第一个object
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git cat-file -t 3cb18
commit # type为commit,表示该object为commit类型
[ locolhost:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git cat-file -p 3cb18
tree 5c6781b18b7c61773120fca8b5006fb9cba71e49 #type为tree,类似目录
author ljzsdut <lijuzhang@inspur.com> 1649487010 +0800
committer ljzsdut <lijuzhang@inspur.com> 1649487010 +0800
1st commit
# 第2个object
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git cat-file -t 5c67
tree
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git cat-file -p 5c67
100644 blob 500403283f5ed39ff656d0acfaf7ce4ec22494dd git.txt
100644 blob 8d0e41234f24b6da002d962a26c2495ea16a425f tmp.txt
其他文件:
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ cat .git/HEAD
ref: refs/heads/master #指向的分支
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ cat .git/refs/heads/master
3cb18e8893083b917ab79b34afa7bca9e3cfd426 #指向commit
此时的结构图:

再进行一次commit:
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ echo 1 >>tmp.txt
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ git add tmp.txt
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ git commit -m "2nd commit"
[master 61b3faa] 2nd commit
1 file changed, 1 insertion(+)
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ tree .git
.git
├── COMMIT_EDITMSG
├── HEAD
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects
│ ├── 0f
│ │ └── b63a8ddc80b787a97949e5cf276089790eb81d #tree
│ ├── 3c
│ │ └── b18e8893083b917ab79b34afa7bca9e3cfd426
│ ├── 50
│ │ └── 0403283f5ed39ff656d0acfaf7ce4ec22494dd
│ ├── 5c
│ │ └── 6781b18b7c61773120fca8b5006fb9cba71e49
│ ├── 61
│ │ └── b3faa3de3bf8d11d6d4d811833cbf92151c1e6 #commit
│ ├── 8d
│ │ └── 0e41234f24b6da002d962a26c2495ea16a425f
│ ├── info
│ └── pack
└── refs
├── heads
│ └── master
└── tags
17 directories, 26 files
发现又多了2个object:
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git cat-file -p 61b3faa
tree 0fb63a8ddc80b787a97949e5cf276089790eb81d
parent 3cb18e8893083b917ab79b34afa7bca9e3cfd426
author ljzsdut <lijuzhang@inspur.com> 1649488386 +0800
committer ljzsdut <lijuzhang@inspur.com> 1649488386 +0800
2nd commit
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git cat-file -p 0fb63a8
100644 blob 500403283f5ed39ff656d0acfaf7ce4ec22494dd git.txt
100644 blob 500403283f5ed39ff656d0acfaf7ce4ec22494dd tmp.txt
此时结构图如下:

当有目录时:
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ mkdir folder1
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ echo file3 >folder1/file3.txt
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ git add .
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ✗ ➜ git commit -m "3rd commit"
[master 916cedf] 3rd commit
1 file changed, 1 insertion(+)
create mode 100644 folder1/file3.txt
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ tree .git
.git
├── COMMIT_EDITMSG
├── HEAD
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects
│ ├── 0f
│ │ └── b63a8ddc80b787a97949e5cf276089790eb81d
│ ├── 3c
│ │ └── b18e8893083b917ab79b34afa7bca9e3cfd426
│ ├── 50
│ │ └── 0403283f5ed39ff656d0acfaf7ce4ec22494dd
│ ├── 5c
│ │ └── 6781b18b7c61773120fca8b5006fb9cba71e49
│ ├── 61
│ │ └── b3faa3de3bf8d11d6d4d811833cbf92151c1e6
│ ├── 6f
│ │ └── 1c48e7934b61a9eaecea3fe3c8832073ea0a7a
│ ├── 7c
│ │ └── 8ac2f8d82a1eb5f6aaece6629ff11015f91eb4
│ ├── 8d
│ │ └── 0e41234f24b6da002d962a26c2495ea16a425f
│ ├── 91
│ │ └── 6cedf33208cc0031d838fc942481ac11fd432b
│ ├── b4
│ │ └── 540ce0bad63a0f40de1619b97a4589a9259496
│ ├── info
│ └── pack
└── refs
├── heads
│ └── master
└── tags
21 directories, 30 files
发现多了3个object:
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git cat-file -p 916cedf
tree 6f1c48e7934b61a9eaecea3fe3c8832073ea0a7a #object_1
parent 61b3faa3de3bf8d11d6d4d811833cbf92151c1e6
author ljzsdut <lijuzhang@inspur.com> 1649489508 +0800
committer ljzsdut <lijuzhang@inspur.com> 1649489508 +0800
3rd commit
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git cat-file -p 6f1c48
040000 tree b4540ce0bad63a0f40de1619b97a4589a9259496 folder1 #object_2
100644 blob 500403283f5ed39ff656d0acfaf7ce4ec22494dd git.txt
100644 blob 500403283f5ed39ff656d0acfaf7ce4ec22494dd tmp.txt
[ locolhost:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git cat-file -p b4540c
100644 blob 7c8ac2f8d82a1eb5f6aaece6629ff11015f91eb4 file3.txt #object_3
此时的结构图:

上图中,中间一层的那些tree,被称之为“root tree”。
git add产生的object,默认会自动使用zlib进行单个object的压缩。
对于一个文件,如果存在多次修改并git add操作,每次操作都会产生一个blob类型的object,即便该文件只是修改了一个字符,新产生的object也是一个全量的object,这就导致同一个文件的object的多个版本有大量的冗余部分,浪费存储空间。此时我们可以使用git gc命令进行delta压缩操作。
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git gc
Enumerating objects: 10, done.
Counting objects: 100% (10/10), done.
Delta compression using up to 8 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (10/10), done.
Total 10 (delta 0), reused 0 (delta 0)
压缩后,会在object目录下生成1个pack目录。每次压缩会产生一个idx和pack文件。
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ tree .git/objects
.git/objects
├── info
│ └── packs
└── pack
├── pack-3e76639f57843d61a0bc09b7f9c9d33a69afd4c5.idx
└── pack-3e76639f57843d61a0bc09b7f9c9d33a69afd4c5.pack
2 directories, 3 files
可以使用命令git verify-pack -v <path_to_idx_or_pack_file>进行解析pack文件:
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git verify-pack -v .git/objects/pack/pack-3e76639f57843d61a0bc09b7f9c9d33a69afd4c5.idx
916cedf33208cc0031d838fc942481ac11fd432b commit 219 149 12
61b3faa3de3bf8d11d6d4d811833cbf92151c1e6 commit 219 150 161
3cb18e8893083b917ab79b34afa7bca9e3cfd426 commit 171 120 311
7c8ac2f8d82a1eb5f6aaece6629ff11015f91eb4 blob 6 15 431
500403283f5ed39ff656d0acfaf7ce4ec22494dd blob 12 21 446
6f1c48e7934b61a9eaecea3fe3c8832073ea0a7a tree 104 87 467
b4540ce0bad63a0f40de1619b97a4589a9259496 tree 37 48 554
0fb63a8ddc80b787a97949e5cf276089790eb81d tree 70 54 602
5c6781b18b7c61773120fca8b5006fb9cba71e49 tree 70 75 656
8d0e41234f24b6da002d962a26c2495ea16a425f blob 10 19 731
non delta: 10 objects
.git/objects/pack/pack-3e76639f57843d61a0bc09b7f9c9d33a69afd4c5.pack: ok
对pack文件进行解压缩:
git unpack-objects命令在解压缩时,如果对象已经存在object目录下(无论是object per file形式还是pack包形式),则不会解压缩出该对象。所以一般操作的时候,需要先把pack文件从object目录下移走,然后再解压:
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ mv .git/objects/pack/pack-3e76639f57843d61a0bc09b7f9c9d33a69afd4c5.pack .git/objects
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ tree .git/objects
.git/objects
├── info
│ └── packs
├── pack
│ └── pack-3e76639f57843d61a0bc09b7f9c9d33a69afd4c5.idx
└── pack-3e76639f57843d61a0bc09b7f9c9d33a69afd4c5.pack
2 directories, 3 files
# 解压缩
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git unpack-objects < .git/objects/pack-3e76639f57843d61a0bc09b7f9c9d33a69afd4c5.pack
Unpacking objects: 100% (10/10), done.
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ tree .git/objects
.git/objects
├── 0f
│ └── b63a8ddc80b787a97949e5cf276089790eb81d
├── 3c
│ └── b18e8893083b917ab79b34afa7bca9e3cfd426
├── 50
│ └── 0403283f5ed39ff656d0acfaf7ce4ec22494dd
├── 5c
│ └── 6781b18b7c61773120fca8b5006fb9cba71e49
├── 61
│ └── b3faa3de3bf8d11d6d4d811833cbf92151c1e6
├── 6f
│ └── 1c48e7934b61a9eaecea3fe3c8832073ea0a7a
├── 7c
│ └── 8ac2f8d82a1eb5f6aaece6629ff11015f91eb4
├── 8d
│ └── 0e41234f24b6da002d962a26c2495ea16a425f
├── 91
│ └── 6cedf33208cc0031d838fc942481ac11fd432b
├── b4
│ └── 540ce0bad63a0f40de1619b97a4589a9259496
├── info
│ └── packs
├── pack
│ └── pack-3e76639f57843d61a0bc09b7f9c9d33a69afd4c5.idx
└── pack-3e76639f57843d61a0bc09b7f9c9d33a69afd4c5.pack
12 directories, 13 files
# 删除冗余的pack文件
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ rm -rf .git/objects/pack-3e76639f57843d61a0bc09b7f9c9d33a69afd4c5.pack
pack机制一般用于本地仓库和远程仓库通信时使用,可以节省网络带宽,提高工作效率。缺点是操作pack文件,需要实时计算解压,操作比较慢。
步骤:1、git gc 2、git prune
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git gc
Enumerating objects: 13, done.
Counting objects: 100% (13/13), done.
Delta compression using up to 8 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (13/13), done.
Total 13 (delta 1), reused 9 (delta 0)
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ tree .git/objects
.git/objects
├── 47
│ └── eda11bc3f7e5ae255b4acb266df938f70bc27a
├── fb
│ └── a977ffe3bb65cb9d6c9dba3106b498f6d0167e
├── info
│ └── packs
└── pack
├── pack-2d0f79f64bd327645172e062b2488f268a443770.idx
└── pack-2d0f79f64bd327645172e062b2488f268a443770.pack
4 directories, 5 files
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git prune --dry-run # 查看可以清理的垃圾对象。或使用git fsck查看dangling的对象
47eda11bc3f7e5ae255b4acb266df938f70bc27a blob
fba977ffe3bb65cb9d6c9dba3106b498f6d0167e blob
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ git prune
[ Mac-mini:/Users/lijuzhang/test/git-demo ] git:(master) ➜ tree .git/objects
.git/objects
├── info
│ └── packs
└── pack
├── pack-2d0f79f64bd327645172e062b2488f268a443770.idx
└── pack-2d0f79f64bd327645172e062b2488f268a443770.pack
2 directories, 3 files
git add会产生object:每个文件会产生一个blob类型的object;
目录不会产生对象,其信息会记录在index文件中
当有目录时,即file1,git commit 会产生2个object:一个commit类型的object和一个tree类型的object(不产生blob类型的对象);
当没有目录时,即dir1/file1,git commit 会产生3个object,一个commit类型、1个被commit引用的tree类型、一个被tree引用的子tree,该子tree对象用于表示目录;