代码之家  ›  专栏  ›  技术社区  ›  kkrugler

如何从git repo中移除未引用的blob

git
  •  98
  • kkrugler  · 技术社区  · 16 年前

    我有一个GitHub repo,它有两个分支-master&release。

    release分支包含的二进制分发文件导致了非常大的repo大小(>250MB),所以我决定清理一下。

    首先我删除了远程发布分支,通过 git push origin :release

    然后我删除了本地发布分支。首先我试过 git branch -d release ,但吉特说 “错误:分支'release'不是当前头的祖先。” 那是真的,所以我做了 git branch -D release 强制删除。

    但我在本地和GitHub上的存储库规模仍然很大。然后我浏览了git命令的常用列表,比如 git gc --prune=today --aggressive ,没有运气。

    按照查尔斯贝利的指示 SO 1029969 我得到了一份大块头的名单。然后我使用了 SO 460331 找到斑点……五个最大的不存在,虽然发现较小的斑点,所以我知道脚本是有效的。

    我认为这些博客是来自发布分支的二进制文件,在删除分支之后,它们不知怎么就被留下了。怎样才能摆脱他们?

    10 回复  |  直到 9 年前
        1
  •  196
  •   MultiplyByZer0 Joke_Sense10    7 年前

    ... 不用再麻烦了,我可以向您介绍这个有用的命令“git gc all”,它保证可以删除 全部的 你的git垃圾,直到它们可能会出现额外的配置变量:

    git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc
    

    你可能还需要先运行这样的程序,哦,天哪,git很复杂!!

    git remote rm origin
    rm -rf .git/refs/original/ .git/refs/remotes/ .git/*_HEAD .git/logs/
    git for-each-ref --format="%(refname)" refs/original/ | xargs -n1 --no-run-if-empty git update-ref -d
    

    你可能还需要删除一些标签,谢谢Zitrax:

    git tag | xargs git tag -d
    

    我把这些都写进剧本里了: git-gc-all-ferocious .

        2
  •  70
  •   Community Mohan Dere    9 年前

    如前所述 here ,简单使用

    git reflog expire --expire-unreachable=now --all
    git gc --prune=now
    

    git reflog expire --expire-unreachable=now --all 删除中无法访问的提交的所有引用 reflog .

    git gc --prune=now 移除提交本身。

    敬告 :仅使用 git gc--prune=现在 将无法工作,因为这些提交仍在reflog中引用。因此,必须清除重新记录。

        3
  •  33
  •   Community Mohan Dere    9 年前

    如中所述 this SO answer , git gc 实际上可以增加回购的规模!

    另见 this thread

    现在git有了一个安全机制 不 运行时立即删除未引用的对象' 吉特gc '.
    默认情况下,未引用的对象将保留2周。这是为了方便您恢复意外删除的分支或提交,或者避免一场竞赛,即刚创建但尚未被引用的对象可能被 吉特gc '进程并行运行。

    因此,为了给打包但未引用的对象一个宽限期,重新打包过程将那些未引用的对象从包中推出,使其成为松散的形式,这样它们就可以老化并最终被修剪。
    但是,变得不被引用的对象通常没有那么多。拥有404855个未引用的对象是相当多的,而首先通过克隆发送这些对象是愚蠢的,是对网络带宽的完全浪费。

    不管怎样。。。为了解决你的问题,你只需要跑 吉特gc '与 --prune=now 参数以禁用该宽限期并立即除去那些未引用的对象(只有在没有其他git活动同时发生时才安全,这在工作站上应该很容易确保)。

    顺便说一句,用' git gc --aggressive '使用更高版本的git(或' git repack -a -f -d --window=250 --depth=250 ')

    这个 same thread mentions :

     git config pack.deltaCacheSize 1
    

    这将增量缓存大小限制为一个字节(实际上是禁用它),而不是默认的0,这意味着无限制。这样我就可以使用上面的 git repack 在x86-64系统上使用4个线程(这是一个四核)的命令,内存为4GB。不过,常驻内存使用量增长到近3.3GB。

    如果您的机器是SMP,并且您没有足够的RAM,那么您可以将线程数减少到只有一个:

    git config pack.threads 1
    

    此外,您还可以使用 --window-memory argument 去 git重新打包 '.
    例如,使用 --window-memory=128M 应该在三角洲保持一个合理的上限 搜索内存使用情况,但如果回购协议 包含许多大文件。


    在过滤器的分支前面,你可以考虑(谨慎地) this script

    #!/bin/bash
    set -o errexit
    
    # Author: David Underhill
    # Script to permanently delete files/folders from your git repository.  To use 
    # it, cd to your repository's root and then run the script with a list of paths
    # you want to delete, e.g., git-delete-history path1 path2
    
    if [ $# -eq 0 ]; then
        exit 0
    fi
    
    # make sure we're at the root of git repo
    if [ ! -d .git ]; then
        echo "Error: must run this script from the root of a git repository"
        exit 1
    fi
    
    # remove all paths passed as arguments from the history of the repo
    files=$@
    git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch $files" HEAD
    
    # remove the temporary history git-filter-branch otherwise leaves behind for a long time
    rm -rf .git/refs/original/ && git reflog expire --all &&  git gc --aggressive --prune
    
        4
  •  19
  •   Jakub Narębski adamtaub    16 年前

    git gc --prune=now ,或低水平 git prune --expire now .

        5
  •  12
  •   vdboor    16 年前

    每次你的头移动,git都会在 reflog . 如果删除了提交,则仍有“悬挂提交”,因为它们仍被 重新记录 大约30天。这是删除意外提交时的安全网。

    你可以使用 git reflog 命令删除特定的提交、重新打包等,或者只删除高级命令:

    git gc --prune=now
    
        6
  •  4
  •   nachoparker    9 年前

    你可以用 git forget-blob .

    用法很简单 git forget-blob file-to-forget . 你可以在这里得到更多信息

    https://ownyourbits.com/2017/01/18/completely-remove-a-file-from-a-git-repository-with-git-forget-blob/

    它将从历史记录、刷新、标记等所有提交中消失

    我时不时遇到同样的问题,每次我必须回到这篇文章和其他文章,这就是为什么我自动化了这个过程。

    向Sam Watkins等撰稿人致谢

        7
  •  2
  •   Jorge Torres    8 年前

    尝试使用 git-filter-branch -它不删除大blob,但可以从整个repo中删除指定的大文件。对我来说,它将回购大小从数百MB减少到12 MB。

        8
  •  1
  •   Armali    11 年前

    在做之前 git filter-branch 和 git gc ,您应该查看回购协议中的标记。任何一个真正的系统,如果对诸如持续集成和部署之类的东西有自动标记,那么这些标记仍然会引用不需要的对象,因此 gc 不能移除它们,你仍然会想,为什么回购规模仍然如此之大。

    摆脱所有不想要的东西的最好方法就是跑 git-filter &安培; 吉特gc 然后将master推到一个新的裸机回购协议。新的光秃秃的回购协议将把这棵树清理干净。

        9
  •  0
  •   StellarVortex    14 年前

    有时,“gc”没有多大用处的原因是有一个未完成的基于旧提交的回扣或隐藏。

        10
  •  0
  •   Tanguy    13 年前

    要添加另一个提示,请不要忘记使用 git远程修剪 在使用之前删除远程的过时分支 吉特gc

    你可以看到他们 查看所有的分支

    当您从github和分叉存储库中获取信息时,它通常很有用。。。