众所周知,我们可以定期运行
git gc
来打包.git/objects
下的对象。
在远程中央 Git 存储库(裸露或非裸露)的情况下,经过多次推送后,
myproj.git/objects
下有很多文件;每次提交似乎都会在那里创建一个新文件。
如何打包这么多文件? (我的意思是远程中央裸存储库上的那些,而不是本地克隆存储库上的。)
远程存储库应配置为在提交后根据需要运行 gc。请参阅
gc.auto
和 git-gc
手册页中的 git-config
文档。
但是,远程存储库不需要那么多垃圾收集,因为它很少有悬空(无法访问)提交。这些通常是由分支删除和变基之类的事情造成的,这些通常只发生在本地存储库中。
所以需要更多的gc进行重新打包,这是为了节省存储空间而不是清除实际的垃圾。
gc.auto
变量足以解决这个问题。
GitHub 存储库中的垃圾现在很常见,因为典型的 PR 工作流程涉及大量的强制推送和变基。
但是,无论是否在 GitHub 上,您都无法影响远程存储库中的 GC。仅当您对托管存储库的远程系统具有 shell 访问权限时,才可以执行此操作。换句话说,垃圾收集必须是存储库所在计算机上的本地操作。
GitHub确实做了GC,但它是在无形中发生的。有时,如果不遵循最佳实践,就会产生不幸且令人惊讶的后果。例如,可以在另一个项目中基于源的依赖项中引用 PR 的提交哈希,同时等待 PR 被上游接受。如果该 PR 分支随后被重新设置基础,源依赖项将继续工作一段时间,因为如果已知其哈希值,仍然可以获取悬空提交。
但是,当 GH 确实在存储库上执行 GC 时,另一个项目的构建将突然因“缺少引用”错误而中断,因为依赖项的存储库中不再存在提交。这可能非常令人困惑,尤其是当设置源依赖项的人不再存在时。更重要的是,弄清楚丢失的哈希最初指的是什么可能非常困难,因为它不再是任何分支的一部分。
如果你很幸运,提交仍然存在于尚未被垃圾收集的存储库的某人克隆中,并且引用日志可用于找出提交最初位于哪个分支。然后源依赖关系可以可以更新为使用 PR 的重新基版本,或者如果 PR 现已合并,则可以完全删除。
这个故事的寓意:在 PR 中提及提交时要非常小心。它们不稳定,可能会在没有警告的情况下消失。
虽然你应该有一些进程来定期、自动地处理这个问题,但运行是没有问题的
git gc
在裸存储库上
git@domU:/pix/git/repositories/abd.git$ ls -l
total 28
drwxrwxr-x 2 git git 6 2010-06-06 02:44 branches
-rw-rw-r-- 1 git git 66 2010-06-06 02:44 config
-rw-r--r-- 1 git git 23 2011-03-15 18:19 description
-rw-rw-r-- 1 git git 23 2010-06-06 02:44 HEAD
drwxrwxr-x 2 git git 4096 2010-06-06 02:44 hooks
drwxrwxr-x 2 git git 20 2010-06-06 02:44 info
drwxrwxr-x 260 git git 8192 2010-09-01 00:26 objects
drwxrwxr-x 4 git git 29 2010-06-06 02:44 refs
$ git gc
Counting objects: 3833, done.
Compressing objects: 31% (1085/3500)...
多次推送后,
下有很多文件myproj.git/objects
git 2.11+(2016 年第 4 季度)和预接收挂钩不会有那么多。
在这种情况下,您根本不必触发
git gc
。
请参阅 commit 62fe0eb、commit e34c2e0、commit 722ff7f、commit 2564d99、commit 526f108(2016 年 10 月 3 日),作者:Jeff King (
peff
)。 gitster
-- 合并于 commit 25ab004,2016 年 10 月 17 日)
:隔离对象直至预接收接受receive-pack
为了让“git Push”的接收端检查接收到的历史记录并决定拒绝推送,从发送端发送的对象需要可供钩子和连接检查机制使用,这是传统上通过将对象存储在接收存储库中并让“
”使其过期来完成。git gc
相反,将新接收到的对象存储在临时区域中,并仅在我们执行操作时重用备用对象存储机制来使它们可用。 决定我们是否接受检查,一旦我们决定,要么将它们迁移到存储库,要么立即清除它们。
该临时区域将由新的环境变量设置
GIT_QUARANTINE_ENVIRONMENT
。
这样,如果(大)推送被
pre-receive
钩子拒绝,这些大对象就不会闲置 90 天等待 git gc
清理它们。