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的实现原理有关:

  1. 有一个LFS大文件系统专门存储大文件,而真正Git仓库中的大文件被替换为指向LFS大文件的指针文件。
  2. 在clone时只会将大文件的指针文件传输到客户端,在checkout时才会真正的去下载大文件。
  3. 文件指针和大文件的转换是git内部处理的,用户能看到的还是大文件。
  4. 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,但趟的这些坑还是要记录下来,给有需要的伙伴参考和借鉴。

参考资料

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐