Git LFS 简介
Git LFS 是由 Atlassian, GitHub 和其他开源贡献者开发的 Git 扩展,目的是减少大文件对 Git 仓库的影响,其以一种偷懒的方式下载相关版本的文件。具体来讲,就是只有在执行 checkout
命令时才会下载文件,而 clone
或 fetch
均不会下载文件。
Git LFS 通过将仓库中的大文件替换为一个 指针文件 来达到这一目的。
- 当你向仓库添加文件时,Git LFS 将文件内容替换为一个指针,并将实际文件存储在本地 Git LFS cache 中.
- 当你向服务器推送新的提交,任何被新提交引用的 Git LFS 文件会从本地 Git LFS cache 传送到与远程 Git 仓库关联的远程 Git LFS store 中.
- 当你从一个包含 Git LFS 指针的提交中检出文件时,指针会被替换回本地 Git LFS cache 中的文件,或者从远程 Git LFS store 中下载文件.
Git LFS 的这些操作都是无缝集成的,不会影响你现有的 Git 工作流。你会发现 git clone
或 git pull
非常快,因为你不会下载每一个提交版本中的大文件,它只会下载你实际需要 checkout
的那个提交的大文件。
下载安装包
-
Linux 用户: 可以通过 PackageCloud 获取 Debian 和 RPM 安装包.
-
macOS 用户: 可以通过 Homebrew 安装,
brew install git-lfs
. -
Windows 用户: Git LFS 已经包含在 Git for Windows,也可以通过 Chocolatey 包管理器安装最新版本.
-
二进制安装包: Linux, macOS, Windows, and FreeBSD 还可以通过二进制安装包安装.
安装
使用二进制安装包安装
$ VERSION=v2.7.2
$ DISTRO=linux-amd64
$ tar xvzf git-lfs-${DISTRO}-${VERSION}.tar.gz
$ ./install.sh
Git LFS initialized.
安装脚本会执行以下操作:
-
Install Git LFS binaries onto the system
$PATH
-
Run
git lfs install
to perform required global configuration changes.
$ git-lfs version
git-lfs/2.7.2 (GitHub; linux amd64; go 1.12.4; git 08a08ae0)
创建新的 Git LFS 仓库
$ mkdir lfs-repo
$ cd lfs-repo
$ git init
$ git lfs install
Updated pre-push hook.
Git LFS initialized.
这会在你的仓库安装一个 pre-push
钩子,在你执行 git push
时将 Git LFS 文件上传到服务器.
克隆 Git LFS 仓库
你可以像平常一样克隆一个 Git LFS 仓库,只有在检出默认分支 (通常是 master) 时才会自动下载需要的大文件。Git LFS 每检出一个指针文件,就会下载对应的大文件。
克隆或拉取时不下载 LFS 大文件
方法1:
GIT_LFS_SKIP_SMUDGE=1 git clone repository-url
方法2:
git lfs install --skip-smudge
--skip-smudge
会将如下选项添加到位于 ~/.gitconfig
或 ~/.config/git/config
的全局 git config 文件:
filter.lfs.required=true
filter.lfs.clean=git-lfs clean — %f
filter.lfs.smudge=git-lfs smudge --skip — %f
filter.lfs.process=git-lfs filter-process --skip
如果只想要某个仓库不下载 LFS 大文件,可以配置该仓库的本地 git config 选项
git lfs install --local --skip-smudge
恢复下载 LFS 大文件
恢复默认下载 LFS 大文件的话,只需要重新执行下面的命令
git lfs install
只下载某些文件或全部文件
下载单个文件
git lfs pull --include='filepath'
下载全部文件
git lfs pull
将下载的二进制文件恢复为 Pointer 文件
# 恢复所有文件
git reset --hard HEAD
# 恢复单个文件
git checkout HEAD -- filename
从二进制文件得到对应 Pointer 文件内容
git lfs pointer --file='filepath'
参考链接
加速仓库克隆
如果你克隆的仓库包含很多大文件,可以使用 git lfs clone
命令来提高性能。不同于一次下载一个文件,该命令会在 checkout
结束时,批量下载需要检出的大文件。这会大大减少 HTTP 请求和生成进程的数量 (在 Windows 系统尤其明显)。
拉取和检出
和克隆一样,使用 git pull
拉取 Git LFS 仓库,任何需要的 Git LFS 文件会在拉取完成并开始检出的过程中自动下载。
如果因为某些异常而检出失败,你可以使用 git lfs pull
下载缺失的 Git LFS 文件。
加速拉取
像 git lfs clone
一样,git lfs pull
会批量下载 Git LFS 文件。假如你知道远程仓库提交了大量新文件,你可能不希望在检出时自动一个个下载,而是用 git lfs pull
批量下载,可以在 git pull
时使用 -c
选项来覆盖原有配置:
git -c filter.lfs.smudge= -c filter.lfs.required=false pull && git lfs pull
简单起见,可以把它写成一个别名
git config --global alias.plfs "\!git -c filter.lfs.smudge= -c filter.lfs.required=false pull && git lfs pull"
git plfs
这会提高下载大量 Git LFS 文件时的性能 (同样,尤其在 Windows 上)
让 Git LFS 跟踪文件
当你向仓库添加一个新类型的大文件时,你需要使用 git lfs track
命令告诉 Git LFS 通过指定的模式来跟踪这个文件:
$ git lfs track "*.tgz"
Tracking *.tgz
执行完 git lfs track
你会发现,在执行命令的目录下产生了一个叫 .gitattributes 的文件,这是 Git 为匹配模式的文件绑定特殊行为的机制。Git LFS 会自动产生或更新这个文件,将指定模式的文件绑定到 Git LFS filter
.
为了方便维护,应该只在仓库根目录执行 git lfs track
命令,将所有 Git LFS 模式都记录在根目录的 .gitattributes
文件里。
使用不带参数的 git lfs track
命令显示所有被 Git LFS 跟踪的模式
$ git lfs track
Listing tracked patterns
*.tgz (.gitattributes)
Listing excluded patterns
可以从 .gitattributes
文件删除对应的模式来让 Git LFS 停止跟踪对应的文件,或者执行 git lfs untrack
命令:
$ git lfs untrack "*.tgz"
Untracking "*.tgz"
在不同主机间迁移 Git LFS 仓库
可以使用 git lfs fetch --all
和 git lfs push --all
将 Git LFS 仓库迁移到另一个主机,例如,
git clone --bare https://github.com/exampleuser/old-repository.git
cd old-repository.git
git lfs fetch --all
git push --mirror https://github.com/exampleuser/new-repository.git
git lfs push --all https://github.com/exampleuser/new-repository.git
获取额外的 Git LFS 文件
像在不同主机间迁移 Git LFS 仓库中讲的,使用 git lfs fetch --all
可以获取你仓库中的所有 Git LFS 文件:
$ git lfs fetch --all
Scanning for all objects ever referenced...
✔ 23 objects found
Fetching objects...
Git LFS: (9 of 9 files, 14 skipped) 2.06 MB / 2.08 MB, 2.83 MB skipped
删除本地 Git LFS 文件
可以使用 git lfs prune
命令删除本地 Git LFS cache 中的大文件
$ git lfs prune
✔ 4 local objects, 33 retained
Pruning 4 files, (2.1 MB)
✔ Deleted 4 files
这会删除 旧的 Git LFS 文件,旧文件是不被下列提交对象引用的文件:
-
当前检出的提交
-
还没有被推送的提交
-
最近的提交
可以使用 git lfs prune --dry-run
来测试多少文件会被删掉
$ git lfs prune --dry-run
✔ 4 local objects, 33 retained
4 files would be pruned (2.1 MB)
或者具体哪些文件会被删除
$ git lfs prune --dry-run --verbose
✔ 4 local objects, 33 retained
4 files would be pruned (2.1 MB)
* 4a3a36141cdcbe2a17f7bcf1a161d3394cf435ac386d1bff70bd4dad6cd96c48 (2.0 MB)
* 67ad640e562b99219111ed8941cb56a275ef8d43e67a3dac0027b4acd5de4a3e (6.3 KB)
* 6f506528dbf04a97e84d90cc45840f4a8100389f570b67ac206ba802c5cb798f (1.7 MB)
* a1d7f7cdd6dba7307b2bac2bcfa0973244688361a48d2cebe3f3bc30babcf1ab (615.7 KB)
使用 --verify-remote
选项在删除本地 Git LFS 文件前检查远程 Git LFS store 是否已经有一份拷贝
git lfs prune --verify-remote
这会让删除过程非常慢,但会保证你删除的文件可以从远程恢复。你可以使用 lfs.pruneverifyremotealways
选项让检查始终开启:
git config --global lfs.pruneverifyremotealways true