14.2 暂存区操作引入的临时对象
暂存区操作有可能在对象库中产生临时对象,例如,文件反复地修改、反复地向暂存区添加,或者添加到暂存区后不提交甚至直接撤销,就会产生垃圾数据占用磁盘空间。为了说明临时对象的问题,需要准备一个大的压缩文件,10MB即可。
在Linux上与内核匹配的initrd文件(内核启动加载的内存盘)就是一个大的压缩文件,可以用于此节的示例。将大的压缩文件放在版本库外的一个目录上,因为这个文件会多次用到。
$cp/boot/initrd.img-2.6.32-5-amd64/tmp/bigfile
$du-sh/tmp/bigfile
11M/tmp/bigfile
将这个大的压缩文件复制到工作区中,复制两份。
$cd/path/to/my/workspace/i-am-admin
$cp/tmp/bigfile bigfile
$cp/tmp/bigfile bigfile.dup
然后将工作区中两个内容完全一样的大文件加入暂存区。
$git add bigfile bigfile.dup
查看一下磁盘空间占用:
工作区连同版本库共占用33MB。
$du-sh.
33M.
其中版本库只占用了11MB。版本库空间占用是工作区的一半。
如果再有谁说版本库空间占用一定比工作区大,可以用这个例子回击他。
$du-sh.git/
11M.git/
看看版本库中对象库内的文件,会发现多出了一个松散对象。之所以添加两个文件而只有一个松散对象,是因为Git对于文件的保存是将内容保存为blob对象中,和文件名无关,相同内容的不同文件会共享同一个blob对象。
$find.git/objects/-type f
.git/objects/2e/bcd92d0dda2bad50c775dc662c6cb700477aff
.git/objects/pack/pack-969329578b95057b7ea1208379a22c250c3b992a.idx
.git/objects/pack/pack-969329578b95057b7ea1208379a22c250c3b992a.pack
如果不想提交,想将文件撤出暂存区,则进行如下操作。
(1)查看当前暂存区的状态。
$git status-s
A bigfile
A bigfile.dup
(2)将添加的文件撤出暂存区。
$git reset HEAD
(3)通过查看状态,看到文件被撤出暂存区了。
$git status-s
?? bigfile
?? bigfile.dup
文件撤出暂存区后,在对象库中产生的blob松散对象仍然存在,通过查看版本库的磁盘占用就可以看出来。
$du-sh.git/
11M.git/
Git提供了git fsck命令,可以查看到版本库中包含的没有被任何引用关联的松散对象。
$git fsck
dangling blob 2ebcd92d0dda2bad50c775dc662c6cb700477aff
标识为dangling的对象就是没有被任何引用直接或间接关联到的对象。这个对象就是前面通过暂存区操作引入的大文件的内容。如何将这个文件从版本库中彻底删除呢?Git提供了一个清理的命令:
$git prune
用git prune清理之后,会发现:
用git fsck查看,没有未被关联到的松散对象。
$git fsck
版本库的空间占用也小了10MB,证明大的临时对象文件已经从版本库中删除了。
$du-sh.git/
236K.git/