如何收缩.git文件夹

时间:2011-04-10 17:05:51

标签: linux git

我目前的基数总大约是。 200MB。

但我的.git文件夹的大小惊人,为5GB(!)。因为我把我的工作推到外部服务器,我不需要任何大的本地历史...

如何缩小.git文件夹以释放笔记本上的空间?我可以删除超过30天的所有更改吗?

非常感谢任何帮助:)

7 个答案:

答案 0 :(得分:79)

你不应该删除超过30天的所有更改(我认为它可能在某种程度上利用git,但实际上不推荐)。

您可以调用git gc --aggressive --prune,它将在您的存储库中执行垃圾收集并修剪旧对象。你有很多经常改变的二进制文件(档案,图像,可执行文件)吗?那些通常导致巨大的.git文件夹(记住,git存储每个修订版本的快照和二进制文件压缩很差)

答案 1 :(得分:50)

以下是git Linus的创建者关于如何缩小git repo的内容:

  

相当于“git gc --aggressive” - 但是*正确* - 是   做(过夜)像

   git repack -a -d --depth=250 --window=250
     

深度的东西只是三角洲链的深度   (让他们的历史更久 - 这是值得的空间开销),和   窗口的事情是关于我们想要每个delta的对象窗口有多大   候选人扫描。

     

在这里,你可能想要添加“-f”标志(这是“全部丢弃”   旧的三角洲“,因为你现在正在努力确保这一个   实际上找到了好的候选人。

来源:http://gcc.gnu.org/ml/gcc/2007-12/msg00165.html

这会消除在我的仓库中孤立的二进制数据吗?“git repack”不会删除您已检入您的仓库然后将其删除的图像或二进制数据。要从您的仓库中永久删除这类数据,您必须重新编写历史记录。一个常见的例子就是你不小心在git中检查你的密码。您可以返回并删除一些文件,但之后您必须重新编写您的历史记录,然后强制将新的仓库推送到您的原点。

答案 2 :(得分:8)

5GB vs 200MB有点奇怪。尝试运行git gc

但不,除非您将存储库拆分为模块,否则无法减小.git目录的大小。

git repo的每个克隆都是一个完整的存储库,可以充当服务器。这是分布式版本控制的基本原则。

答案 3 :(得分:2)

我使用git作为同步机制而不是版本历史。所以我对这个问题的解决方法是确保我所有当前的源都处于令人满意的状态,然后删除.git并重新初始化repos。磁盘空间问题解决了。 :-)历史不见了:-( 我这样做是因为我的回购是在一个小USB密钥上。我不想要或不需要我的整个历史。 如果我有一个只是截断历史的方法,我会用它。

如果我有兴趣保留我的历史记录,我会将当前存储库存档。 稍后我可以克隆原始存储库,复制所有更改 新的回购(让我们假设我没有做太多(任何)重命名或删除)。然后做一个 大提交,它将新repo中所做的所有更改表示为单个提交 老回购。是否有可能合并历史?也许如果我使用分支然后 删除了我不需要的对象。 (我不太了解git internals,开始像这样愚弄。)

答案 4 :(得分:2)

通过根据最近更新时间从.git文件夹中删除一些文件日志历史记录来缩小Git存储库。

我在本地计算机上也遇到了同样的问题。原因是我从本地删除了一些海量文件,并提交给中央存储库。但是在git statusgit fetchgit pull之后的事件。我的.git文件夹大小约为3GB。稍后我运行以下命令,以通过考虑一个月前更改/过期的文件来减小.git文件夹的大小。

命令

$ git remote prune origin && git repack && git prune-packed && git reflog expire --expire=1.month.ago && git gc --aggressive

Git命令及其简短描述:

  • git-prune-从对象数据库中修剪所有无法访问的对象
  • git-repack-在资源库中打包未打包的对象
  • git-prune-packed-删除打包文件中已经存在的多余对象。
  • git reflog:Git使用称为参考日志或“ reflogs”的机制来跟踪分支尖端的更新。 Reflog跟踪本地存储库中Git ref的更新时间。除了分支提示刷新外,还为Git存储库保留了一个特殊刷新。引用日志存储在本地存储库的.git目录下的目录中。 git reflog目录可以在.git/logs/refs/heads/..git/logs/HEAD.git/logs/refs/stash上找到(如果回购中已使用git stash)。 Rewriting History页面上的git reflog高级别。
    git reflog expire --expire=now --expire-unreachable=now --all
    除了在reflog中保留历史记录外,Git还具有内部到期日期,该日期将修剪何时分离的提交。同样,这些都是git gc处理的所有实现细节,git prune不应单独使用。
  • git gc --aggressivegit-gc-清理不必要的文件并优化本地存储库。
    在幕后,git gc实际上执行了一堆其他内部子命令,例如git prune, git repack, git pack and git rerere。这些命令的高级职责是识别在git gc配置中设置的阈值级别之外的所有Git对象。一旦确定,这些对象将被压缩或相应地修剪。

成果与成就:

$ git remote prune origin && git repack && git prune-packed && git reflog expire --expire=1.month.ago && git gc --aggressive
Enumerating objects: 535, done.
Counting objects: 100% (340/340), done.
Delta compression using up to 2 threads
Compressing objects: 100% (263/263), done.
Writing objects: 100% (340/340), done.
Total 340 (delta 104), reused 0 (delta 0)
Enumerating objects: 904, done.
Counting objects: 100% (904/904), done.
Delta compression using up to 2 threads
Compressing objects: 100% (771/771), done.
Writing objects: 100% (904/904), done.
Total 904 (delta 343), reused 561 (delta 0)

答案 5 :(得分:0)

尝试了上述方法,在我的情况下(在git push期间意外杀死git进程)没有任何效果,因此我最终不得不删除该repo并再次对其进行克隆,现在.git文件夹大小正常。

答案 6 :(得分:0)

如何缩小 git 仓库中的 .git 文件夹

TLDR;

按此顺序,从最不危险和/或最有效和/或最快到更危险和/或效率较低和/或最慢:

这些测试结果针对的是一个存储库,其中 du -hs --exclude=.git . 显示总存储库大小(不包括 .git 目录)约为 80 GB,并且 { {1}} 显示 du -hs .git 文件夹单独开始时大约 162 GB

.git

如您所见,最后一个命令花费了很长时间,但收益很小,所以不要运行它!

详情

首先,您需要知道 .git 文件夹中的内容占用了如此多的空间。一种技术是在您的存储库中运行 ncurses-base(类似 GUI)# Memory Saved # Time it took in .git dir # ------------ ------------ time git lfs prune # 1~60 min 62 GB time git gc # 3 min < 1 GB time git prune # 1 min < 1 GB time git repack -a -d --depth=250 --window=250 # 2 min < 1 GB time git gc --aggressive --prune # 1.25 hrs < 1 GB (NCurses 磁盘使用)命令。另一种方法是运行这个:

ncdu

旁注:要查看您的存储库有多大,不包括您的 du -h --max-depth=1 .git 文件夹,请改为运行:

.git

上面第一个命令的示例输出:

<块引用>
du -h --max-depth=1 --exclude=.git .

如您所见,我的 $ du -h --max-depth=1 .git 158G .git/lfs 6.2M .git/refs 4.0K .git/branches 2.5M .git/info 3.7G .git/objects 6.2M .git/logs 68K .git/hooks 162G .git 文件夹总大小为 162 GB,但其中 158 GB 是我的 .git 文件夹,因为我我正在使用第 3 方“Git Large File Storage" (git lfs)”工具来存储大型二进制文件。因此,运行它以显着减少这种情况。注意:以下所有命令的 .git/lfs 部分是可选的:

time

(如果 time git lfs prune 因“恐慌:运行时错误:无效的内存地址或空指针取消引用”而失败,请参阅下面的注释。)

来源:How to shrink a git LFS repo
官方文档:git-lfs-prune(1) -- Delete old LFS files from local storage

运行需要60秒

现在我刚刚释放了 62 GB!我的 git lfs prune 文件夹现在只有 96 GB,如下所示:

<块引用>
.git/lfs

接下来,运行此命令将 $ du -h --max-depth=1 .git 96G .git/lfs 6.2M .git/refs 4.0K .git/branches 2.5M .git/info 3.0G .git/objects 6.2M .git/logs 68K .git/hooks 99G .git 文件夹缩小几百 MB 到 ~1 GB 左右:

.git/objects

time git gc time git prune 运行大约需要 3 分钟,而 git gc 需要大约 1 分钟。

使用 git prune 再次检查您的磁盘使用情况。如果您想节省更多空间,请运行以下命令:

du -h --max-depth=1 .git

这大约需要 2 分钟并节省数百 MB。

现在,你可以停在这里,或者你可以运行这个最后的命令:

time git repack -a -d --depth=250 --window=250

最后的命令将节省数百 MB,但大约需要 1.25 小时。

如果 time git gc --aggressive --prune 失败并显示“恐慌:运行时错误:无效的内存地址或空指针取消引用”

如果 git lfs prune 失败:

<块引用>

恐慌:运行时错误:无效的内存地址或空指针取消引用

那么您可能安装了旧版本的 git lfs prune 并且需要更新它。方法如下:

首先,检查您安装的版本。运行 git-lfs 并滚动到底部以查看日期。例如,也许它说它是从 2017 年开始的。现在,使用这些命令更新您的版本。第一个命令来自这里:https://packagecloud.io/github/git-lfs/install

man git-lfs

再次运行 curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash sudo apt update sudo apt install git-lfs 并滚动到底部。我现在将我的日期视为“2021 年 3 月”,而之前是 2017 年的某个日期。

此外,如果我再次运行 man git-lfs,它会告诉我:

<块引用>

git-lfs 已经是最新版本(2.13.3)。

因此,sudo apt install git-lfs 的更新成功了,现在错误消失了,git-lfs 再次生效!

我首先在 GitHub 上的评论中记录了这一点:https://github.com/git-lfs/git-lfs/issues/3395#issuecomment-889393444

参考:

  1. @knittl:How to shrink the .git folder
  2. @David Dehghan:How to shrink the .git folder
  3. git lfs pruneHow to shrink a git LFS repo
  4. git lfs prune 上的 Linus Torvalds:https://gcc.gnu.org/legacy-ml/gcc/2007-12/msg00165.html
  5. https://github.com/git-lfs/git-lfs/blob/main/docs/man/git-lfs-prune.1.ronn

另见:

  1. [我的问答] How to resume `git lfs post-checkout` hook after failed `git checkout`
<子> 关键词:git clean dir;清理 .git 目录;清理 .git 文件夹;压缩 .git 文件夹;可用硬盘空间 git;压缩 .git 目录;收缩 .git 目录;减少 .git 目录