Yikun / yikun.github.com

Yikun's Blog
69 stars 22 forks source link

大文件在Github和Gitee上传的建议 #87

Open Yikun opened 3 years ago

Yikun commented 3 years ago

本文详细解释了在github及gitee上对大文件处理的限制以及解决方案。

Github和Gitee文件大小限制

托管类型 单文件限制 单仓库限制 LFS单文件限制 LFS单账户限制
Github 100MB 建议小于1GB,强烈建议小于5GB 2GB 1GB
Gitee 50MB 500MB 仅对企业付费用户开放 仅对企业付费用户开放

简单说,如果gitee通过非LFS方式,上传了100MB以上的文件,那么github无法镜像。gitee通过LFS方式,上传了100MB以上的文件,最大不能超过2GB,且总和不能超过1GB。否则会出现this exceeds GitHub's file size limit of 100.00 MB错误:

root@yikun-x86:~/yikun/bigfile# git push origin main
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 4 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 120.25 MiB | 191.00 KiB/s, done.
Total 6 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
remote: error: Trace: 58b4554c41925fcfb5dba5ec99aebb5ef9fab8d092461cb8ed321578a4fa178e
remote: error: See http://git.io/iEPt8g for more information.
remote: error: File boost_1_72_0.tar.gz is 120.72 MB; this exceeds GitHub's file size limit of 100.00 MB
To github.com:Yikun/bigfile.git
 ! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'git@github.com:Yikun/bigfile.git'

1. 如何处理大文件(超过100MB的文件)

任何方案,都需要处理最近一次commit(通过删除或者LFS改造)和历史所有commits的提交(通过bfg)

第一步:处理当前大文件(最近一次commit)

image

  1. 找到大文件。通过git big-filesgit blob-find找到所有出现问题的分支。

  2. 处理大文件[推荐] 方案一(删除大文件,并保留历史提交): 通过自动化下载和脚本的方式,此步完成后,所有的大文件在lastest commit都被清除。 方案二(利用LFS改造大文件,并保留历史提交): lfs方式改造大文件。在每个分支通过git lfs方式进行改造,此步完成后,所有的大文件在lastest commit都改造为lfs方式。

第二步:处理历史大文件(历史所有commits)

image

清除历史大文件。利用bfg工具,清除所有历史大文件提交记录。(注意:此步会重新提交每个commits,大文件的commit会被替换为xxx.remove的flag文件)

2. 详细解释

2.1 如何找到所有大文件的历史提交及大文件对应的分支?

把下面的配置copy到~/.gitconfig的底部:

[alias]
    big-files = !"git rev-list --objects --all \
                 | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
                 | sed -n 's/^blob //p' \
                 | sort -nk2 \
                 | cut -c 1-12,41- \
                 | $(command -v gnumfmt || echo numfmt) --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest"
    blob-find = "!f() { \
        obj_name="$1"; \
        shift; \
        git log --pretty=format:'%T %h %s' \
        | while read tree commit subject ; \
        do \
            if git ls-tree -r $tree | grep -q "$obj_name" ; \
            then \
                echo $commit "$subject"; \
                git --no-pager branch -a --contains $commit ; \
            fi; \
        done; \
        }; f"
  1. git big-files: 找出所有的大文件blob。

    ➜  samples git:(dev) ✗ git big-files | tail -3
    41d83dcfd6bb   32MiB mark_detection_video_cpp/for_atlas300_1.3x.0.0/script/maskdetection.om
    514c780be5c6   49MiB mark_detection_video_cpp/for_atlas300_1.3x.0.0/script/peppapigdetection.om.bak
    96cf9e58c3e4  119MiB c++/level2_simple_inference/2_object_detection/YOLOV3_coco_detection_VENC/model/yolov3.om

    可以看到最大的文件的blob hash是96cf9e58c3e4,大小是119MiB,路径为c++/level2_simple_inference/2_object_detection/YOLOV3_coco_detection_VENC/model/yolov3.om

  2. git blob-find: 找到blob所在提交和分支。

    ➜  samples git:(dev) ✗ git blob-find 96cf9e58c3e4
    4290b1a commit YOLOV3_coco_detection_multi_thread_VENC
    * dev
    remotes/origin/dev
    59d12cb commit YOLOV3_coco_detection_VENC
    * dev
    remotes/origin/dev

可以看到96cf9e58c3e4这个blob,在dev分支的4290b1a、59d12cb这两个commits有提交或者修改。

2.2 删除大文件。通过lfs方式改造大文件 或者 删除大文件

方案一:删除大文件

rm -rf file
git add file
git commit
git push

方案二:通过lfs方式改造大文件

# 安装git lfs
git lfs install

# 跟踪大文件
git lfs track "*.psd"
git add .gitattributes

# 提交大文件
git add file.psd
git commit -m "Add design file"
git push origin main

参考:https://git-lfs.github.com/

2.3 如何清除所有分支历史的大文件

https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/removing-sensitive-data-from-a-repository#using-the-bfg

# 注意:这里通过mirror方式clone,最后一步push会影响所有分支。
git clone --mirror git://example.com/some-big-repo.git

java -jar bfg.jar --strip-blobs-bigger-than 100M some-big-repo.git

$ cd some-big-repo.git
$ git reflog expire --expire=now --all && git gc --prune=now --aggressive

$ git push
Lee-robbie commented 2 years ago

手动删除某个大文件历史信息方法: 1、根据git big-files: 找出所有的大文件blob。 2、重写commit,删除大文件
使用以下命令,删除历史提交过的大文件: git filter-branch --force --index-filter 'git rm -rf --cached --ignore-unmatch xxx/xxx/' --prune-empty --tag-name-filter cat -- --all 上面脚本中的xxx/xxx/请换成你第一步查出的大文件名,或者这里直接写一个目录。 清理和回收空间
虽然上面我们已经删除了文件, 但是我们的repo里面仍然保留了这些objects, 等待垃圾回收(GC), 所以我们要用命令彻底清除它, 并收回空间,命令如下: rm -rf .git/refs/original/ git reflog expire --expire=now --all git gc --prune=now git gc --aggressive --prune=now 3、推送修改后的repo 以强制覆盖的方式推送你的repo, 命令如下: git push --force git remote prune origin

Yikun commented 2 years ago

@Lee-robbie Thanks!