• 请不要在回答技术问题时复制粘贴 AI 生成的内容
bonfy
V2EX  ›  程序员

Git 问题求教 - git rm 大文件但是.git 文件夹还是很大,怎么处理

  •  
  •   bonfy · Dec 1, 2016 · 6899 views
    This topic created in 3477 days ago, the information mentioned may be changed or developed.
    git 的时候不小心把 test 的内容都 commit 进去了

    (我明明已经加.gitignore 了,还是会 add 进去。。。当然这个我先不纠结了)

    现在的问题是已经 rm 了,但是.git 里面还是有 pack 文件很大,怎么搞呢,明明就是几 kb 的事,现在 clone 下来就是几 MB,99%都是.git 里面的 pack 文件

    老司机有遇到这个问题的么? 除了重新建 Repo 还有其他法子不?
    24 replies    2016-12-02 05:57:56 +08:00
    fds
        1
    fds  
       Dec 1, 2016
    你怎么 rm 的?把 commit 从历史版本里删掉了么?没有的话用 git reset --hard 回到以前,然后 git push --force 强制覆盖。
    lrh3321
        2
    lrh3321  
       Dec 1, 2016
    都已经被提交过了就无解了
    除非你先 checkout 到 commit 之前
    然后, 把最新分支的内容覆盖一次
    接着,重新提交
    再 -f 推送到服务器
    song4
        3
    song4  
       Dec 1, 2016
    一旦文件添加进去,就一直在里面了,直接 rm 是没办法把这个文件从历史提交里面移除的。

    你需要的是把文件从整个历史里面抹掉:

    git filter-branch --index-filter \
    'git rm --cached --ignore-unmatch path/to/your/file' \
    --tag-name-filter cat -- --all
    bonfy
        4
    bonfy  
    OP
       Dec 1, 2016
    @fds 没把 commit 删掉。。。 我试试 git reset...
    bonfy
        5
    bonfy  
    OP
       Dec 1, 2016
    @lrh3321 已经提交了。。。。
    bonfy
        6
    bonfy  
    OP
       Dec 1, 2016
    @song4 我试试。。。
    Citrus
        7
    Citrus  
       Dec 1, 2016   ❤️ 2
    先说方法,你需要这个简单的小工具:
    https://rtyley.github.io/bfg-repo-cleaner/

    然后说原理:
    因为 Git 会记录你 所有 的历史提交,所以为了回滚需要,只要是在 Git 中存在过一次的文件,就会被永久记录下来,不论当前是否存在。
    bonfy
        8
    bonfy  
    OP
       Dec 1, 2016
    @Citrus  这个牛,都已经上升到工具了。。。 Star 好多,看来和我同样问题的 git 新手好多
    TangMonk
        9
    TangMonk  
       Dec 1, 2016
    git rm --cached test
    fan123199
        11
    fan123199  
       Dec 1, 2016
    @song4 git filter-branch --index-filter \
    'git rm --cached --ignore-unmatch path/to/your/file' \
    --tag-name-filter cat -- --all

    这个方法学习了,但是不知道对其他成员有没有影响(比如他 pull 或 push 时出错。)。 git 官方说, 修改 public repo 的已有 commit , 会有大影响。
    song4
        12
    song4  
       Dec 1, 2016
    @fan123199 如果调用了这个方法,在向远端 push 的时候,必须强制覆盖:

    git push origin --force --all


    所以这是一个危险操作,务必再三确认啊!
    fan123199
        13
    fan123199  
       Dec 1, 2016
    @bonfy 这不是新手问题,如果你的 test 变动还在 HEAD ,那么很简单,按 1L 办,如果又加了新 commit ,那就难办了,所以要认真对待每个 commit ,特别是 push 的时候。
    song4
        14
    song4  
       Dec 1, 2016
    另外,分享一篇文章, Github 官方帮助告诉你怎样从仓库里彻底移除敏感信息: https://help.github.com/articles/remove-sensitive-data/
    fan123199
        15
    fan123199  
       Dec 1, 2016
    @song4 这个时候,是不是跟 filter 有关的 commit 的 hash 值都会变成新的。如果是的话,感觉是重做了整个 branch 的感觉。这个在公有 repo 还是太危险,行不通。 最好只在本地完成。
    song4
        16
    song4  
       Dec 1, 2016
    @fan123199 确实是你说的这样。

    建议尽量不要用这个极端的方法,除非在某些极端的情况下(比如不小心把密钥提交到了版本库里)。
    laiqs2011
        17
    laiqs2011  
       Dec 1, 2016
    git gc 试试?
    bonfy
        18
    bonfy  
    OP
       Dec 1, 2016
    @chousb 这个好像就是 @song4 提的那个。 不过有小弟还是令人羡慕啊:)
    shibingsw
        19
    shibingsw  
       Dec 1, 2016
    @song4 这个正解
    msg7086
        20
    msg7086  
       Dec 1, 2016
    @fan123199 文件就在历史里,你要么改变历史,要么接受历史。
    删除文件的话,当然所有 Hash 都要变的。
    fivesmallq
        21
    fivesmallq  
       Dec 1, 2016
    之前遇到过 ,可以参考下 http://nll.im/post/clean-up-git-repo.html
    bonfy
        22
    bonfy  
    OP
       Dec 1, 2016
    谢谢各位,我最后还是 git reset , git push --force 重新提交解决的

    核弹级选项: filter-branch 估计也是正解,但是看着就吓人,没勇气尝试。。。
    Sunnyyoung
        23
    Sunnyyoung  
       Dec 1, 2016
    ## 命令

    `git filter-branch --tree-filter 'rm -rf test/' --tag-name-filter cat HEAD --all`

    ## 说明

    `--all` : 所有分支
    `--tree-filter`: 需要执行的命令
    `--tag-name-filter cat` : Tag 也做修改
    DravenJohnson
        24
    DravenJohnson  
       Dec 2, 2016
    需要 Clean 历史 Commit ,后晌几个说的都可以
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3285 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 86ms · UTC 13:13 · PVG 21:13 · LAX 06:13 · JFK 09:13
    ♥ Do have faith in what you're doing.