14.5 Git管家的自动执行

对于老版本库的Git,会看到帮助手册中建议用户对版本库进行周期性的整理,以便获得更好的性能,尤其是对于规模比较大的项目,但是对于整理的周期都语焉不详。

实际上对于1.6.6及以后版本的Git已经基本上不需要手动执行git gc命令了,因为部分Git命令会自动调用git gc—auto命令,在版本库确实需要整理的情况下自动开始整理操作。

目前有如下的Git命令会自动执行git gc—auto命令,实现对版本库的按需整理。

执行命令git merge进行合并操作后,对版本库进行按需整理。

执行命令git receive-pack,即版本库接收其他版本库PUSH来的提交后,对版本库进行按需整理操作。

当版本库接收到其他版本库的PUSH请求时,会调用git receive-pack命令以接收请求。在接收到推送的提交后,对版本库进行按需整理。

执行命令git rebase-i进行交互式变基操作后,会对版本库进行按需整理。

执行命令git am对mbox邮箱中通过邮件提交的补丁在版本库中进行应用的操作后,会对版本库做按需整理操作。

综上所述,对于提供共享式“写操作”的Git版本库,可以免维护。所谓的共享式写操作,就是版本库作为一个裸版本库放在服务器上,团队成员可以通过PUSH(推送)操作将提交推送到共享的裸版本中。每一次推送操作都会触发git gc—auto命令,对版本库进行按需整理。

还有,对于非独立工作的本地工作区,也可以免维护。因为和他人协同工作的本地工作区会经常执行git pull操作从他人版本库或从共享的版本库拉回新提交,执行git pull操作会触发git merge操作,因此也会对本地版本库进行按需整理。

在对版本库进行按需整理时,整理的频率是一个问题。如果整理得太勤则没有必要,还会增加系统负担;但如果疏于整理则会导致积累太多的松散文件,当真正开始版本库整理的时候会占用过多的系统资源,影响用户体验。因此实际操作中只有在特定的条件下才会触发真正的版本库整理。

主要的触发条件是:松散对象只有超过一定的数量时才会执行。在统计松散对象数量时,为了降低在.git/objects/目录下搜索松散对象对系统造成的负担,实际采取了取样搜索,即只会对对象库下的一个子目录.git/objects/17进行文件搜索。在默认的配置下,只有该目录中对象数目超过27个才会触发版本库的整理。至于为什么只在对象库中选择一个子目录进行松散对象的搜索,这是因为SHA1哈希值是完全随机的,文件在由前两位哈希值组成的目录中差不多是平均分布的。至于为什么选择17,不知道对于作者Junio C Hamano有什么特殊意义,也许是向Linus Torvalds被评选为20世纪最有影响力的100人中排名第17位而致敬[1]

可以通过设置配置变量gc.auto的值,调整Git管家自动运行时触发版本库整理操作的频率。默认gc.auto的值为6700,是触发版本库整理的全部松散对象数的阈值,对于单个取样目录.git/objects/17来说,超过(6700+255)/256个文件时即开始版本库整理。但是注意不要将gc.auto设置为0,否则git gc—auto命令永远不会触发版本库的整理。

[1]http://en.wikipedia.org/wiki/Linus_Torvalds