为什么有这个需求
有些小伙伴可能会好奇,为什么要把非文本文件纳入到git中管理,我们平时写的代码不都是文本文件吗?但是大千世界,无奇不有,下面的这几种情况还真是需要git来管理非文本文件:
- 前端开发的资源文件,大部分都是高清的图片资源,尤其是移动端开发,需要适配不同的屏幕尺寸,同时UI设计师们可能随时修改资源文件
- 后端同学用到了一个供应商开发的库文件,不提供源码,只有二进制形式,文件很大,前期修改频繁
- 嵌入式开发里面用到了一个特定版本的编译器。例如手机厂商在开发android系统时,git库里面就有各种版本的arm-gcc编译器
有的小伙伴可能会说,如果有需求的话,直接放进去不就可以了,为什么要特殊处理。其实这话也不算错,前提是这样的文件小且修改不频繁。因为Git对于非文本文件是全量存储,也就是每个版本都有一个完整的拷贝,同时git仓库默认会把所有的历史版本下载到本地,如果文件很大且修改频繁,就会导致整个git仓库巨大无比,进而下载起来非常的慢,幸福感直线下降。
如何解决
可惜的是,原生Git并没有解决这个问题,问题是被Atlassian、Github以及部分开源爱好者解决的,这就是Git LFS(Large File Storage)-大文件存储。它是一个Git插件,需要单独安装。有了它,你就可以用Git来管理那些大的二进制文件,而不必担心版本更新导致的Git库爆仓的问题。它使用了一种指针的机制来记录版本信息,同时将实际文件存放到另外一个目录中,在Git克隆的过程中,不会下载所有历史版本,而是根据需要,下载特定的某个版本,默认只下载最新版本。
效率高吗?为什么?
相对于原生的Git管理方式,LFS的方式由于不需要一次性的下载所有历史版本,首次下载速度不会有很大影响。但是由于历史版本还在远端,如果需要切换不同的版本,就会临时下载对应的版本,这样实际上是把下载的过程在时间维度上离散化了。对于不关心历史版本的人来说,降低了下载时长。
具体怎么做
安装
1
2
3
4
5
6
7
8
|
## mac系统
brew install git-lfs
## ubuntu系统安装
sudo apt install git-lfs
## 当前用户启用lfs(用户级设置)
git lfs install
|
## mac系统
brew install git-lfs
## ubuntu系统安装
sudo apt install git-lfs
## 当前用户启用lfs(用户级设置)
git lfs install
跟踪/取消跟踪文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
## 跟踪根目录下的所有png文件,但不包含子目录
$ git lfs track '*.png'
## 跟踪所有目录下的png文件
$ git lfs track '**/*.png'
## 跟踪res目录下的所有文件,包含子目录
$ git lfs track 'res/**'
## 跟踪res目录下的所有文件,不包含子目录
$ git lfs track 'res/*'
## 跟踪根目录下的所有已经存在的zip文件,后续新增的不算(因为你的shell会将*.zip转译为所有已经存在的zip文件列表)
$ git lfs track *.zip
## 取消对所有ogg文件的跟踪
git lfs untrack '*.ogg'
## 由于跟踪的规则记录在.gitattributes文件中,因此修改规则需要保存对这个文件的修改
git add .gitattributes
git add .
## 推送到远端仓库
git push
## 查看lfs管理了哪些文件
git lfs ls-files
|
## 跟踪根目录下的所有png文件,但不包含子目录
$ git lfs track '*.png'
## 跟踪所有目录下的png文件
$ git lfs track '**/*.png'
## 跟踪res目录下的所有文件,包含子目录
$ git lfs track 'res/**'
## 跟踪res目录下的所有文件,不包含子目录
$ git lfs track 'res/*'
## 跟踪根目录下的所有已经存在的zip文件,后续新增的不算(因为你的shell会将*.zip转译为所有已经存在的zip文件列表)
$ git lfs track *.zip
## 取消对所有ogg文件的跟踪
git lfs untrack '*.ogg'
## 由于跟踪的规则记录在.gitattributes文件中,因此修改规则需要保存对这个文件的修改
git add .gitattributes
git add .
## 推送到远端仓库
git push
## 查看lfs管理了哪些文件
git lfs ls-files
切换版本
和日常的切换版本一样,不需要额外的命令:
在切换版本的时候,.git/lfs/
目录下会下载历史版本,同时将工作目录中的内容切换为对应的版本。
疑问
- 对于已经处于Git管理的二进制文件,是否可以使用LFS管理?
可以,但使用LFS之前的历史记录不受影响。但使用LFS之后,新的文件版本会被放到LFS中进行管理,后续克隆仓库的时候,只克隆一个版本。
- Git服务端支持吗?
现有的服务端软件都支持LFS,只是免费托管的仓库,对LFS的存储空间有限制,例如Github可以免费使用2GB空间。
- 为什么LFS没有直接合入Git主线,而要用插件的方式单独安装
具体原因不详,不过小编猜测,LFS的解决方式和Git分布式版本管理的理念不符,因为默认LFS无法离线切换版本,需要联网才行。另外就是如果按照Git的分布式设计理念,其实这个问题无解(既要分布式离线可用,又要库占用的空间小),所以思来想去,还是不要放到主线版本里吧。
参考