git-lfs的安装和使用
git是分布式版本系统,clone时会将文件的所有版本都传输到客户端,如果遇到大文件,初始clone就会需要很长时间,也就是说大文件会导致Git出现性能瓶颈。知道了这个原理,有一个思路是:可以只clone LFS大文件的指针,而不下载原始文件。
1. 背景
尝试从huggingface上下载数据集时,很多数据集都要求必须安装git-lfs。
为什么需要git-lfs呢?
原因在于:git是分布式版本系统,clone时会将文件的所有版本都传输到客户端,如果遇到大文件,初始clone就会需要很长时间,也就是说大文件会导致Git出现性能瓶颈。
为了解决这个问题,Git引入了Git LFS(Large File Storage)——专门用于管理大型文件的扩展。
而很多数据集都是上百M甚至上G的,所以基本都需要使用git-lfs才能clone。
2. 安装git-lfs
对于mac系统,很多教程都是使用homebrew包管理器来一条命令安装。
brew install git-lfs
结果装到最后就出现一些奇怪的报错:
Running `brew update --auto-update`...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core and homebrew/cask).
……
curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to mirrors.ustc.edu.cn:443
Warning: Bottle missing, falling back to the default domain...
==> Downloading https://ghcr.io/v2/homebrew/core/libyaml/manifests/0.2.5
Already downloaded: /Users/a200007/Library/Caches/Homebrew/downloads/5f6b0af1730aa1bc02f8021c90ed7ffe988eeba95eec83e6c828f77332ba6406--libyaml-0.2.5.bottle_manifest.json
==> Downloading https://ghcr.io/v2/homebrew/core/libyaml/blobs/sha256:83547fba540a38c30705a59a2e746952c68857212e823c6ee97c186e088f75cd
-=O#- # # #
curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to pkg-containers.githubusercontent.com:443
Error: git-lfs: Failed to download resource "libyaml"
Download failed: https://ghcr.io/v2/homebrew/core/libyaml/blobs/sha256:83547fba540a38c30705a59a2e746952c68857212e823c6ee97c186e088f75cd
==> `brew cleanup` has not been run in the last 30 days, running now...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
尝试多次都是报这个错,这类错误往往和系统本地的环境有关系,花费很多时间也不一定有结果。
最后还是得回归到原始方式,尝试从官网上找安装包。
官网包下载地址:https://git-lfs.com/
下载完后是一个zip文件,解压并进入解压的目录:
a200007@xxx~ % cd ~/Downloads/git-lfs-3.5.1
a200007@xxx git-lfs-3.5.1 % ls
CHANGELOG.md README.md git-lfs install.sh man
执行install.sh,输出Git LFS initialized.
就表示安装成功。
a200007@xxx git-lfs-3.5.1 % sudo ./install.sh
Password:
Git LFS initialized.
不放心的话也可以采用git lfs install
来验证,也是输出同样的信息。
Updated Git hooks.
Git LFS initialized.
3. 使用git-lfs
输入命令尝试克隆数据集:
git clone git@hf.co:datasets/jslin09/Fraud_Case_Verdicts
结果在处理文件Corpus-Delicti.csv (130 MB)
时遇到网络错误read: connection reset by peer
,详细日志如下:
Cloning into 'Fraud_Case_Verdicts'...
Warning: Permanently added the ECDSA host key for IP address '34.198.14.237' to the list of known hosts.
remote: Enumerating objects: 823, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 823 (delta 0), reused 0 (delta 0), pack-reused 820 (from 1)
Receiving objects: 100% (823/823), 114.32 KiB | 848.00 KiB/s, done.
Resolving deltas: 100% (183/183), done.
Updating files: 100% (6/6), done.
Downloading Corpus-Delicti.csv (130 MB)
Error downloading object: Corpus-Delicti.csv (05fc481): Smudge error: Error downloading Corpus-Delicti.csv (05fc4815c8eea333c31909a1c034d43d5f8d2dbf17bfa8b5de92ba2ad1c8bed1): batch response: Post "https://huggingface.co/datasets/jslin09/Fraud_Case_Verdicts.git/info/lfs/objects/batch": read tcp 192.168.0.105:64115->3.160.150.2:443: read: connection reset by peer
Errors logged to '/Users/a200007/work/ucgit/github/fraud/dataset/Fraud_Case_Verdicts/.git/lfs/logs/20240721T232114.139161.log'.
Use `git lfs logs last` to view the log.
error: external filter 'git-lfs filter-process' failed
fatal: Corpus-Delicti.csv: smudge filter lfs failed
warning: Clone succeeded, but checkout failed.
You can inspect what was checked out with 'git status'
and retry with 'git restore --source=HEAD :/'
并且不论尝试多少次,都是报这个错误,并且提示Clone succeeded, but checkout failed.
为什么git-lfs会clone成功,而checkout失败呢?
这与git-lfs的实现原理有关:
- 有一个LFS大文件系统专门存储大文件,而真正Git仓库中的大文件被替换为指向LFS大文件的指针文件。
- 在clone时只会将大文件的指针文件传输到客户端,在checkout时才会真正的去下载大文件。
- 文件指针和大文件的转换是git内部处理的,用户能看到的还是大文件。
- git在下载大文件时,会批量并行下载所有必需的LFS文件。
知道了这个原理,有一个思路是:可以只clone LFS大文件的指针,而不下载原始文件。具体方式是添加一个GIT_LFS_SKIP_SMUDGE=1
选项。
GIT_LFS_SKIP_SMUDGE=1 git clone git@hf.co:datasets/jslin09/Fraud_Case_Verdicts
# 也可以通过先执行:git lfs install --skip-smudge,再git clone
Cloning into 'Fraud_Case_Verdicts'...
remote: Enumerating objects: 823, done.
remote: Counting objects: 100% (50/50), done.
remote: Compressing objects: 100% (47/47), done.
remote: Total 823 (delta 29), reused 2 (delta 2), pack-reused 773 (from 1)
Receiving objects: 100% (823/823), 115.94 KiB | 451.00 KiB/s, done.
Resolving deltas: 100% (182/182), done.
但实际试下来,等到用git lfs fetch --all
去单独下载大文件时,还是会卡在0%很长时间不动。
a200007@xxx Fraud_Case_Verdicts % git lfs fetch --all
fetch: 360 objects found, done.
fetch: Fetching all references...
Downloading LFS objects: 0% (0/1), 0 B | 0 B/s
最后去huggingface上看了一圈,发现还有一个办法,可以直接单独下载大文件。
最后终于将数据集下载下来。
小结: 虽然最终下载文件没有使用git-lfs,但趟的这些坑还是要记录下来,给有需要的伙伴参考和借鉴。
参考资料
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)