我使用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,有什么不对?
答案 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尺寸)。