我阅读了许多相关问题,但我遇到了以下问题。
在this repo中,media/1 Juno-Trumpet
中有大型文件(在之前的提交中),因此我完全按照answer here删除了这些文件:
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
问题:为什么回购邮件的尺寸没有变化?如何在清理后使回购尺寸变小?
答案 0 :(得分:3)
运行git filter-branch
实际上复制每次过滤的提交。生成的存储库从不任何小型井,而不是尚未 - 通常更大。如果您幸运或聪明,大多数副本会重复使用大多数原始对象,因此生成的存储库只比原始存储库大一点。
您可能会合理地问:"那么我们为什么要过滤存储库?"事实上,对于每个使用存储库的人来说,大多数情况下你不应该:它是一个非常令人头痛的问题(但通常只是一次性的,至少一次),因为他们都必须切换到新的过滤存储库。但真正的答案是,在过滤之后,您可以删除对原始(预复制)对象的引用,或者将存储库克隆到新的新克隆。
原始物品'引用保存在refs/original/
和中的reflogs中(特别是HEAD
reflog通常会有它们)。如果您选择(出于某些疯狂的原因)不要仅重新克隆已过滤的存储库,请参阅the git filter-branch
documentation末尾的说明,了解如何删除这些说明。
答案 1 :(得分:1)
仍然包含子目录的旧提交仍然是存储库的一部分,即使它们无法从任何分支访问。
清理它们你可以做到
git reflog expire --expire=now --all && git gc --prune=now --aggressive
但是这会清空你的reflog。 这是必要的,因为你的reflog引用的提交不会被垃圾收集
答案 2 :(得分:0)
只是一个即用型完整版,基于@ lucanLepus接受的答案。
假设我是userA
,我想从Github上的repo中完全删除历史记录media/1 Juno-Trumpet/
中的文件夹(在最近的提交中不再存在,但在过去的提交中)。< / p>
注意:此特定存储库具有原始分支master
,sfz
和wifi
以及标记v1.0
。为了避免需要知道这一点,我在这里使用镜像克隆(这使得一个裸存储库,这很好,因为我将使用索引过滤器)。然后,由于这是GitHub,我首先抛弃所有refs/pull/
引用。
事实证明,这些文件也被命名为media/Juno-Trumpet/
和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)
(最后一行表示存储库中的一个标记出现在任何重写的提交之前,即毕竟我们不需要--tag-name-filter cat
。)
现在我们必须删除refs/original/
名称。由于这是一个新的克隆,没有任何reflogs到期,但我们无论如何都会这样做,然后用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
(477145c7d0190f4e0aeea0f7bfb9accbf2c1ba48
是一个较大的.wav
文件。我没有检查删除的所有文件是.wav
个文件以及是否还有其他.wav
个文件。)