本地回购和 bitbucket 的大小差异

Difference in size of a local repo and bitbucket

我有一个本地存储库。我用 du -csh <foldername> 命令检查了 .git 文件夹的大小。它是 168 MB。我将它推送到我的 bitbucket 仓库。我检查了要下载的 repo 的大小只有 134 mb。

这怎么可能?

首先,让我们解决整个存储库的大小问题。 (跳到第二个 header 部分以跳过此部分。)

一般来说,"pure server" 仓库就是Git 所谓的 仓库,也就是没有work-tree.[=17= 的仓库]

请记住,在 any Git 存储库中,1 你有:

  • 曾经做出的每一次提交,以 Git-only 形式存储,加上
  • 与这些提交关联的每个 文件,也以 Git-only 形式存储,加上
  • 一些杂项开销数据(标签、树、参考名称、"info"、挂钩等)。

None 个 2 的形式为 "files you work with normally on your computer",因此如果您打算 任何有提交的东西,除了将它发送给另一个 Git,你可能需要一个 work-tree。服务器上的 --bare 存储库大多只是将提交传输到其他 Git(接收和发送),因此保留一份工作副本是对 space 的浪费,而且实际上适得其反当前提交。

由于服务器省略了工作副本,您通常应该期望 server-side 裸存储库小于 client-side non-bare 存储库。因此,您观察到的结果应该完全不足为奇。 令人惊讶的是,有时服务器大小的存储库 更大 。这有很多可能的原因,最有可能的是服务器上尚未 运行 压缩 / garbage-collection 代码。在某些情况下,您可能需要从 运行 服务器的任何人那里获得帮助。请参阅,例如,How to reduce git repo size on Bitbucket? 完整的详细信息迅速深入到包文件格式、增量压缩 windows、备用 object 目录的杂草中——像 GitHub 这样的网站广泛使用后者是为了防止叉子占用太多 space—等等。


1这会故意忽略浅层或 single-branch 克隆,它们会 运行 在指定位置对历史进行分类,因此会忽略一些或许多提交和文件。

2其实很多Git的内部文件都是plain-text,但也有很多不是,反正你一般应该用什么Git 调用 管道命令 来操作它们,如果您打算编写自己的代码来使用 Git。使用提供的 API——管道命令——使您免受未来旨在使 Git 工作得更好、更快等的更改的影响。


但是您的 .git 只是裸存储库

您将 .git 文件与他们的下载进行了比较。这些都不是或没有 work-tree,那么为什么您的 .git 目录更大?

现在我们必须进入那些杂草,至少一点点。

首先要知道的是Git每个Git有两种形式object:每个提交,每个"blob"(文件),以及每个带注释的标签和树。其中之一是 松散 格式,它只是 zlib-deflated。另一个在打包文件中,压缩程度更高。

当您在 Git 存储库中工作时,您会创建新的松散 object。 Git 最终决定松散的 object 太多占用了太多 space,并将它们打包。这使得它们的检索速度较慢——必须找到它们并解压它们,而不是直接收集它们 re-inflated——但现在它们需要更少的 space.

其次,每次您在 Git 中执行操作时,您都会 添加 新的 object。其中一些永远不会永久保存。这些(通常是松散的)objects 是 Git 所称的 unreferenced: 它们是为了保存它们而创建的,至少是暂时的,也许是永久的,但后来发现它们是不必要的,所以它们被扔在了地板上。

除此之外,每次你变基提交时,你实际上是在复制它们,然后放弃原件。但是 Git 默认情况下会将原件保留至少 30 天,以防您改变主意并想要取回它们。它使用 Git 的 reflogs 来执行此操作。

这就是 Git 的 "garbage collector"、git gc 发挥作用的地方。垃圾收集器——Git 的死神,或者也许是死神收集器——有许多工作,包括弄清楚哪些内容已从 reflog 中老化,应该被丢弃。这可能会使更多 objects 变得未被引用(除了任何已创建但最终被证明是不需要的),因此它接下来会发现 unreferenced loose objects 和 "prunes" 他们。最后,它负责 打包 松散 object 到较小(但访问速度较慢)的打包文件格式。

垃圾收集器会在需要时自动为您获取 运行;你不应该手动 到 运行 它。如果您确实必须手动 运行 它,则表明 Git 中存在某种错误(我读过一些这样的案例,其中的脚本会使松散的 object auto-pruning).请注意,这通常会留下 unrefe不过,至少 14 天后,object 会松动,以防某些事情仍在努力使它们被引用。

[编辑以添加我之前应该提到的最后两项:] 服务器通常 运行 git gc 打包并在每次推送后 clean-up;并且可下载版本有时会 re-当场打包以使其尽可能小,或者至少小到 "automatically possible"(有时您甚至可以制作打包文件通过调整 gc 参数来变小,尽管当我第一次尝试使用 Git 时,我一直把它们变大 :-)).