从git回购中删除文件夹';中国的历史没有';我们不能缩小回购规模

从git回购中删除文件夹';中国的历史没有';我们不能缩小回购规模,git,github,Git,Github,我读了很多相关问题,但我有以下问题 在中,media/1 Juno-brample(在以前的提交中)中有大量文件,因此我严格按照以下步骤删除这些文件: git clone https://github.com/alexmacrae/SamplerBox.git git count-objects -vH 总文件大小:54MB git filter-branch --tree-filter 'rm -rf "media/1 Juno-Trumpet"' --prune-empty HEAD gi

我读了很多相关问题,但我有以下问题

在中,
media/1 Juno-brample
(在以前的提交中)中有大量文件,因此我严格按照以下步骤删除这些文件:

git clone https://github.com/alexmacrae/SamplerBox.git
git count-objects -vH
总文件大小:54MB

git filter-branch --tree-filter 'rm -rf "media/1 Juno-Trumpet"' --prune-empty HEAD
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
echo "media/1 Juno-Trumpet/" >> .gitignore
git add .gitignore
git commit -m 'Removing a folder from git history'
git gc
git count-objects -vH
总文件大小:54MB

git filter-branch --tree-filter 'rm -rf "media/1 Juno-Trumpet"' --prune-empty HEAD
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
echo "media/1 Juno-Trumpet/" >> .gitignore
git add .gitignore
git commit -m 'Removing a folder from git history'
git gc
git count-objects -vH

问题:为什么回购规模没有改变?如何在这样的清理之后减小repo的大小?

仍然包含子目录的旧提交仍然是存储库的一部分,即使无法从任何分支访问它们

你可以把它们清理干净

git reflog expire --expire=now --all && git gc --prune=now --aggressive
然而,这将清空您的reflog。
这是必要的,因为reflog引用的提交不会被垃圾收集

仍然包含子目录的旧提交仍然是存储库的一部分,即使无法从任何分支访问它们

你可以把它们清理干净

git reflog expire --expire=now --all && git gc --prune=now --aggressive
然而,这将清空您的reflog。
这是必要的,因为reflog引用的提交不会被垃圾收集

运行
git filter branch
实际上会复制每个被过滤的提交。由此产生的存储库从来没有更小过,现在还没有,而且通常更大。如果幸运或聪明,大多数副本都会重复使用大多数原始对象,因此生成的存储库只比原始存储库大一点点

您可能会合理地问:“那么,我们为什么要过滤存储库?”事实上,大多数情况下您不应该这样做:对于使用存储库的每个人来说,这都是一个非常头痛的问题(但通常至少是一次性的),因为他们都必须切换到新的过滤存储库。但真正的答案是,在过滤之后,您可以删除对原始(预复制)对象的引用,或者将存储库克隆到新的新克隆


原始对象的引用保存在
refs/original/
和reflogs中(尤其是
HEAD
reflog通常会有它们)。如果您选择(出于某些疯狂的原因)不只是重新克隆已筛选的存储库,请参阅末尾的说明,了解如何删除这些内容。

运行
git filter branch
实际上会复制已筛选的每个提交。由此产生的存储库从来没有更小过,现在还没有,而且通常更大。如果幸运或聪明,大多数副本都会重复使用大多数原始对象,因此生成的存储库只比原始存储库大一点点

您可能会合理地问:“那么,我们为什么要过滤存储库?”事实上,大多数情况下您不应该这样做:对于使用存储库的每个人来说,这都是一个非常头痛的问题(但通常至少是一次性的),因为他们都必须切换到新的过滤存储库。但真正的答案是,在过滤之后,您可以删除对原始(预复制)对象的引用,或者将存储库克隆到新的新克隆


原始对象的引用保存在
refs/original/
和reflogs中(尤其是
HEAD
reflog通常会有它们)。如果您选择(出于某些疯狂的原因)不只是重新克隆筛选后的存储库,请参阅末尾的说明,了解如何删除这些存储库。

根据@lucanLepus的公认答案,这只是一个随时可用的完整版本

假设我是
userA
,我想从Github上的repo中完全删除历史
media/1 Juno-bullent/
(在最近的提交中不再出现,但在很久以前的提交中)中的文件夹

注意:此特定存储库具有原始分支
master
sfz
wifi
,以及标签
v1.0
。为了避免需要知道这一点,我在这里使用了镜像克隆(这会生成一个裸存储库,这很好,因为我将使用索引过滤器)。然后,由于这是GitHub,我首先抛出所有的
ref/pull/
ref

事实证明,这些文件也被命名为
media/Juno-blample/
media/Juno/
,因此我们需要删除所有三个路径名

git clone --mirror https://github.com/alexmacrae/SamplerBox.git
cd SamplerBox.git
git for-each-ref --format="git update-ref -d %(refname)" refs/pull | sh
git for-each-ref         # to check that we have only wanted refs left
git count-objects -vH    # size-pack: 54.40 MiB
git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch "media/1 Juno-Trumpet" media/Juno-Trumpet media/Juno' --prune-empty --tag-name-filter cat -- --all
“过滤器分支”步骤需要一小段时间,并以以下内容结束:

Ref 'refs/heads/master' was rewritten
Ref 'refs/heads/sfz' was rewritten
Ref 'refs/heads/wifi' was rewritten
WARNING: Ref 'refs/tags/v1.0' is unchanged
v1.0 -> v1.0 (7ec3254d08b65fd3ca8a048cef60b5b2c75f7e11 -> 7ec3254d08b65fd3ca8a048cef60b5b2c75f7e11)
(最后一行表示存储库中的一个标记位于任何重写的提交之前,也就是说,我们根本不需要
--tagname filter cat

现在我们必须删除
refs/original/
名称。因为这是一个新的克隆,所以不会有重登录过期,但我们还是要这样做,然后使用
git-gc重新打包

git for-each-ref --format="git update-ref -d %(refname)" refs/original | sh
git reflog expire --expire=now --all
git gc --prune=now --aggressive
git count-objects -vH     # size-pack: 1.41 MiB
我没有完成最后一步:

git push origin '+refs/*:refs/*'
(如果您确实希望所有媒体文件都完全消失,那么您可能还需要清除所有拉取请求,因为它们会保留一段时间)


顺便说一句,我使用以下方法找到了三个名称下的文件:

git cat-file --batch-all-objects --batch-check | sort +2 -rn | head
要查找相对较大的文件,请执行以下操作:

git rev-list --all | while read ref; do
   git ls-tree -r $ref | grep 477145c7d0190f4e0aeea0f7bfb9accbf2c1ba48;
done | sort -u

477145c7d0190f4e0aeea0f7bfb9acbf2c1ba48
是一个大的
.wav
文件。我没有检查是否所有删除的文件都是
.wav
文件,以及是否还有任何其他
.wav
文件。)

根据@lucanLepus接受的答案,只是一个随时可用的完整版本

假设我是
userA
,我想从Github上的repo中完全删除历史
media/1 Juno-bullent/
(在最近的提交中不再出现,但在很久以前的提交中)中的文件夹

注意:此特定存储库具有原始分支
master
sfz
wifi
,以及标签
v1.0
。为了避免需要知道这一点,我在这里使用了镜像克隆(这会生成一个裸存储库,这很好,因为我将使用索引过滤器)。然后,由于这是GitHub,我首先抛出所有的
ref/pull/
ref

事实证明,这些文件也被命名为
media/Juno-blample/
media/Juno/
,因此我们需要删除所有三个路径名

git clone --mirror https://github.com/alexmacrae/SamplerBox.git
cd SamplerBox.git
git for-each-ref --format="git update-ref -d %(refname)" refs/pull | sh
git for-each-ref         # to check that we have only wanted refs left
git count-objects -vH    # size-pack: 54.40 MiB
git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch "media/1 Juno-Trumpet" media/Juno-Trumpet media/Juno' --prune-empty --tag-name-filter cat -- --all
过滤器br