修剪后,Git存储库的大小变为2倍大小

时间:2017-01-12 01:34:38

标签: git gitlab

我使用GitLab Community Edition 8.15.1 1119c1f,Git 2.11(在我的电脑上),Windows 10 pro x64。

我的Git存储库有超过15500次提交。运行命令后

git filter-branch --tree-filter 'rm -rf module_foo/deployment/lib' HEAD

大约6个小时,

我试试

git push origin --force --all -v

我尝试减少Git存储库的大小(通过库中的delete * .jar文件),但它变为 2x旧尺寸。然后我看到(在GitLab web GUI上)Git repsitory的大小从400 MB到800 MB,有什么不对?

2 个答案:

答案 0 :(得分:2)

这是预期的,因为git filter-branch必须通过复制每个过滤的提交。如果在每次提交时运行它,最终结果大约是提交的两倍。但不要惊慌!您只需要重新克隆。有关详细信息,请阅读以下所有背景信息。

参考

请记住,Git的工作方式基于引用。最常见的引用是分支和标记名称。例如,您可能有master分支(也许这是您的分支)。这意味着名称master转换为Git SHA-1哈希ID。尝试运行命令:

git rev-parse master
在shell中

,查看实际的哈希ID。

引用的名称空间

分支名称master实际上是引用 refs/heads/master。引用只是一个通用的分支或标记名称。例如,如果您有一个名为v1.2的标记,那么它实际上只是引用名refs/tags/v1.2。请注意,这些都在refs/下,但分支位于refs/heads/下,而代码位于refs/tags/下。

这些顶级名称创建name spaces,允许多个不同的名称共存而不会发生任何冲突。这样,如果您不小心创建标记 master,它就不会与分支 master发生冲突(这仍然是一个坏主意 - Git会处理它,但你可能会迷惑自己)。

Git的远程跟踪分支同样位于refs/名称空间,即refs/remotes/,后跟远程名称。因此,origin/master确实是refs/remotes/origin/master

引用仅指向一个提交;每个提交指向另一个

所有这些引用名称 - 分支,标记,远程跟踪分支以及refs/stash的{​​{1}}等特殊内容 - 每个都指向一个特定提交 1 Git在存储库中找到提交的所有 rest 的方式是从这些单个提交开始。每个提交都包含一些其他早期提交的ID。大多数提交都有一个以前的提交。至少有一次提交 - 你做过的第一次提交 - 没有之前的提交,并且任何合并提交都有两个先前的提交, 2 ,因为它将这些提交绑定在一起。

大多数情况下,您不需要知道所有这些。但是,当您运行git stash 时,会将所有原始引用保存到git filter-branch。这些原始引用指向原始提交,即refs/original/复制它们之前的所有提交。然后它会替换每个引用中的值以指向复制的提交。

这是您的双倍存储库大小的来源。请注意,如果您使用原始git filter-branch稍微搞了一些东西,可以通过“撤消”过滤器来恢复所有内容-branch,将所有filter-branch引用移回其原始名称(即删除 new 引用并将原件放回原位)。您仍将保留较大的存储库大小,但新副本将不再使用,并且最终将过期(并且不会在新克隆中传输)。

另请注意,您通常希望使用refs/originals/过滤所有分支。如果您有任何带注释的标记,通常需要包含-- --all以便调整标记。

1 或者,对于带注释的标签,引用将指向带注释的标签对象,然后指向提交。非分支引用名称可以指向任何Git的内部对象类型,但“commit”或“tag”以外的任何内容都是不常见的。

2 合并提交可以指回两个以上的提交。这称为章鱼合并。章鱼合并主要用于炫耀你的Git-fu。 :-)也就是说,它没有做任何你不能用几个常规合并做的事情。

缩小存储库

--tag-name-filter cat保存所有这些原件的原因是过滤器分支可能具有极大的破坏性。如果您需要,它可以让您使用逃生舱盖来取回原件。

通常,使用filter-branch的正确方法是在存储库的副本上运行它。如果事情变得严重无关紧要,就没有必要保存一切。 (由于Git的内部机制和约束,你仍然获得副本,但是filter-branch可以为你清除它们。)但是“以防万一”它会留下所有原件。

缩小它的简便方法是在过滤后再次再次克隆存储库。克隆忽略 git filter-branch引用,因此也会跳过复制所有已保存的原始对象。因此,您将立即看到新克隆的大小恢复。

答案 1 :(得分:0)

我执行这些步骤,创建完整备份:

   CREATE UNIQUE INDEX idx_part_id_dynamic ON partition_table part_id,
    (CASE WHEN part_id = 1 THEN name, age
          WHEN part_id = 3 THEN age
          ELSE height
    END );
    );

然后删除名为git clone --mirror http://example.com/git/foo.git cd foo.git git bundle create foo.bundle --all 的存储库, 那么

foo

尺寸会像预期的那样(不会变成2x尺寸)。