Skip to content

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

@Yikun

Description

@Yikun

本文详细解释了在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 '[email protected]: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

  1. 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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions