一、什么是git LFS

LFS是Large File Storage的缩写,用了帮助git管理大的文件

原理:不同于git每次保存diff,对于git来说,如果是模型或者一些设计大文件,改变一点,对于仓库来说会增加很大的体积,不一会就能几个G。对于git lfs来说,在使用git lfs track命令后,git push的时候,git lfs会截取要管理的大文件,并将其传至git lfs的服务器中,从而减小仓库的体积

二、安装方法

注意:git lfs 要求 git >= 1.8.2

1. centos安装方法

可以按照github上提供的安装方法,运行下列命令进行安装:

curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.rpm.sh | sudo bash

sudo yum install git-lfs

git lfs install

在centos上按照官方提供的步骤报错,大概意思是下载不到安装包

使用rpm包安装,从在官网下载安装包安装,安装方法如下:

  • 在上述官网中找到Downloads,然后选择相应的系统安装包下载

  • 对于centos来说,下载rpm(可以通过lsb_release -a查看系统版本)

  • 下载rpm包后使用sudo rpm -ivh 包名.rpm进行安装

  • 运行git lfs install,如果显示Git LFS initialized说明安装成功

2. macos 安装

运行brew install git-lfs即可安装

3. Debian and Ubuntu 安装

1. curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
2. sudo apt-get install git-lfs
3. git lfs install

三、使用方法

  • 告诉lfs需要管理的大文件,比如model.pb,运行命令 git lfs track model.pb
  • 将管理文件.gitattributes添加入git仓库 git add .gitattributes
  • 将大文件添加入git仓库,然后和其它添加方式一样
    git add model.pb
    git commit -m "add model file"
    git push

四、如何将已提交的大文件更新为lfs管理

4.1 更新之前一段历史提交

由于有些仓库开发了一段时间,导致仓库已经有一段提交历史了,并且提交了很多次大文件了,那么这个时候可以有两个方法去完成仓库的大文件管理。

  1. 重新开一个仓库,重新完成提交。这样做法就是丢失了之前的提交记录,而且重新提交很多文件也会比较麻烦。
  2. 采用git lfs的迁移方式将大文件重新采用git lfs去管理。(注意:该方案从git lfs v2.2.1版本后才开始支持。)

开始迁移之前需要重点说明,下面步骤会改变本地有的所有分支,但如果本地没有的分支,是改变不了的,迁移后会造成提交hash值的修改,导致与其它分支可能没法merge的情况。

迁移方法如下:

  • 执行下面命令将待迁移的文件转为使用LFS方式存储管理
    # 这里include后面接待管理的文件,everything表示将本地所有分支都执行这种管理方式(但是实测好像并没有生效,只对当前分支有效),也可以指定分支(参考“参考文献”2)
    git lfs migrate import --include="libs/*.so" --everything
    git lfs migrate import --include="opencv/**/*.a" --everything
  • 执行下面命令将更改推到远程
    # 这里是强推,害怕出错的话,可以先备份一下仓库
    git push --force

这里需要说明的是,如果仓库是很久远的,这样push可能推不上去,会报"this exceeds GitHub’s file size limit of 100.00 MB"之类的错误。是因为要更改的内容太多,要推的东西可能超出的限制,那么可以使用下面脚本进行处理。脚本来源于参考文献3

REMOTE=origin
BRANCH=$(git rev-parse --abbrev-ref HEAD)
# 如果还是报错,可以将这个值设置小一点
BATCH_SIZE=10

# check if the branch exists on the remote
# if git show-ref --quiet --verify refs/remotes/$REMOTE/$BRANCH; then
#     # if so, only push the commits that are not on the remote already
#     range=$REMOTE/$BRANCH..HEAD
# else
#     # else push all the commits
#     range=HEAD
# fi

range=HEAD

echo "Range: $r"

# count the number of commits to push
n=$(git log --first-parent --format=format:x $range | wc -l)

echo "Commits to push: $n"

# push each batch
for i in $(seq $n -$BATCH_SIZE 1); do
    # get the hash of the commit to push
    h=$(git log --first-parent --reverse --format=format:%H --skip $i -n1)
    echo "Pushing $h..."
    git push $REMOTE $h:refs/heads/$BRANCH --force
done

# push the final partial batch
git push $REMOTE HEAD:refs/heads/$BRANCH
  • 虽然现在使用了git lfs去管理文件,但是之前的文件还在,所以需要进行清理。执行下面命令即可。
    git reflog expire --expire-unreachable=now --all
    git gc --prune=now
4.2 更新当前一次提交

在工作中如果提交时忘记了用lfs管理大模型并且已经把该提交push了怎么办。(该方式由视觉理解组同事王超提供,实际操作可行)

注意该方法仍然会保留之前提交的大文件,并把大文件又交给lfs管理,所以仍然会增加git仓库体积,不应该长期使用。提交大文件要习惯用lfs提交。

可以按照安装时的方式执行,重新提交一次

  • git lfs install
  • 告诉lfs需要管理的大文件,比如model.pb,运行命令 git lfs track model.pb
  • 将管理文件.gitattributes添加入git仓库 git add .gitattributes
  • 将大文件添加入git仓库,然后和其它添加方式一样
    git add model.pb
    git commit -m "add model file"
    git push -f # 重新提交管理文件方式变更,需要强行刷新之前的提交

五、注意事项

  1. 由于在不同的文件夹下面执行git lfs track “$filename”,都会生成对应的.gitattributes文件,为了方面管理,最好执行该命令时都在仓库根目录下执行
  2. 执行git lfs track "$filename"命名时,如果2. 执行git lfs track 使用通配符,记得加上双引号。如果不加,通配符会被扩展后加入.gitattributes文件里面。例如git lfs track “*.bin”,添加给文件的是*.bin,如果git lfs track *.bin,添加给.gitattributes文件的是1.bin 2.bin等。
  3. 通配符
# track all .ogg files in any directory
$ git lfs track "*.ogg"
# track files named music.ogg in any directory
$ git lfs track "music.ogg"
# track all files in the Assets directory and all subdirectories
$ git lfs track "Assets/"
# track all files in the Assets directory but *not* subdirectories
$ git lfs track "Assets/*"
# track all ogg files in Assets/Audio but not in subdirectories
$ git lfs track "Assets/Audio/*.ogg"
# track all ogg files in any directory named Music
$ git lfs track "**/Music/*.ogg"
# track png files containing "xxhdpi" in their name, in any directory
$ git lfs track "*xxhdpi*.png
# track bin files in models directory's subdirectories not include mode/*.bin
$ git lfs track "model/**/*.bin"

六、问题记录

6.1 如果遇到如下按照错误

1.jpg

解决办法:查看git lfs版本是不是太新了

6.2 如果遇到Unlink of file Failed. Should I try again?

可能有软件正在打开该仓库,需要关闭所有的相关软件。

参考文献

  1. https://github.com/git-lfs/git-lfs
  2. https://github.com/git-lfs/git-lfs/wiki/Tutorial#migrating-existing-repository-data-to-lfs
  3. https://blog.on2.dev/how-to-migrate-large-git-repositories-ba87c8910915
  4. https://cloud.tencent.com/developer/article/1989489
  5. https://zhuanlan.zhihu.com/p/146683392
Logo

新一代开源开发者平台 GitCode,通过集成代码托管服务、代码仓库以及可信赖的开源组件库,让开发者可以在云端进行代码托管和开发。旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐