1.9. Git 垃圾回收
回收垃圾
随着仓库的增长 git 它可能会自动地将你的对象文件转换成一种更紧密的方式。这种形式被称作 "pack" 文件。
手动回收
你也可以手动运行一个命令去进行这个垃圾回收操作。但是注意这个命令是不可逆的。一旦运行了这个命令之后, Git 就会将这些文件压缩成一个更快更小的打包文件,并且删除掉所有 dangling commits —— 比如从一个已经删除的分支或者没有 merge 的分支。
我们以前学过,是可以通过 git reflog 这个命令来查找我们要恢复的删除的 commit 但是一旦你执行了这个命令之后,这些 dangling commits 就不再能够恢复了。
如何手动回收
好,我们现在来看一下,在那个 demo 这个仓库的根目录下运行 git gc
。
➜ plumbing-demo git:(main) git gc
Enumerating objects: 104, done.
Counting objects: 100% (104/104), done.
Delta compression using up to 4 threads
Compressing objects: 100% (101/101), done.
Writing objects: 100% (104/104), done.
Total 104 (delta 49), reused 0 (delta 0), pack-reused 0
回收效果分析
好,现在就出现了压缩写入之类的操作提示。我们现在再看我们刚才所说的那个 .git/objects 这个目录。你可以看到就跟上一节有很大的差别了,对不对?
➜ plumbing-demo git:(main) ls .git/objects
06 14 23 2d 31 38 47 59 60 71 78 84 8d 95 9b 9f ac b3 ca cf d4 e3 ed f2 fb pack
0a 16 28 2e 34 3e 56 5a 69 73 7f 86 91 96 9c a2 b0 b6 cd d2 d8 e6 ee f3 ff
0b 21 29 30 37 45 57 5f 6c 75 80 88 92 9a 9e a4 b1 b8 ce d3 dc e7 f1 f9 info
这就说明了我们压缩起效果了。
比如我们要找我们上一节提到的 04 那个文件夹。就会发现怎么也找不到了,对不对?就证明这个对象已经被删除掉了或者被压缩掉了,他到底去了哪里呢?我们可以研究一下。
在 object 这个文件夹里面有一个 pack 的文件夹,我们进入这个 pack 的文件夹。
➜ pack git:(main) ls
pack-29cf6365eb4d782ca6954ef7909111f794405ed0.idx pack-29cf6365eb4d782ca6954ef7909111f794405ed0.pack
看到了有两个文件,一个是 idx 后缀,一个是 pack 后缀。我们用 cat 命令来看一看,可以看到是一个二进制的文件。我们再看另外一个文件,也是用 cat 命令可以看到也是一个二进制的文件。因为是二进制文件,这样是查看不了的,但我们可以暂时认为就是压缩到了这里。
而且进行了这个垃圾回收之后,可以看到不仅是我们的这个 .git/objects 文件进行了压缩,还将我们的分支引用也进行了压缩。比如说我们可以看到这个 .git 根目录下有一个 packed-refs 这个 file 产生。
用 cat 命令看一下它的内容。
➜ .git git:(main) cat packed-refs
# pack-refs with: peeled fully-peeled sorted
8f809e04a436df0fccab26ac40cdfc8b32d6ee3d refs/heads/main
f37d6c37d7a2f2d0443b839dac7c13e10ac84239 refs/tags/v1.0
^51871d3a84bb13eccd06022e4962ace4b4d02a62
e8d9ca0d12ce5b17be6e9037507835cd9fdf3abc refs/tags/v2.0
^6423242d1225237121d732f1643038ec94f0eaeb
看到我们的 main head 已经到了这里面。然后我们看一下我们原来的 .git/refs/head 这个目录,发现里面没有东西,
➜ .git git:(main) ls refs/heads/
# nothing
就说明 main head 已经被压缩到这里了。tag 也是如此。
建议
虽然我们的对象被压缩了,但是所有的对象 ID 仍然可用。git gc
这个 命令 只是改变了存储机制,而不是仓库本身的内容。 时不时地运行一下 git gc
通常是一个好主意,可以让你的仓库保持优化。