Git进阶-如何管理非文本文件

2024/06/03 | 字数1882 | 阅读4分钟


为什么有这个需求

有些小伙伴可能会好奇,为什么要把非文本文件纳入到git中管理,我们平时写的代码不都是文本文件吗?但是大千世界,无奇不有,下面的这几种情况还真是需要git来管理非文本文件:

有的小伙伴可能会说,如果有需求的话,直接放进去不就可以了,为什么要特殊处理。其实这话也不算错,前提是这样的文件小且修改不频繁。因为Git对于非文本文件是全量存储,也就是每个版本都有一个完整的拷贝,同时git仓库默认会把所有的历史版本下载到本地,如果文件很大且修改频繁,就会导致整个git仓库巨大无比,进而下载起来非常的慢,幸福感直线下降。

如何解决

可惜的是,原生Git并没有解决这个问题,问题是被Atlassian、Github以及部分开源爱好者解决的,这就是Git LFS(Large File Storage)-大文件存储。它是一个Git插件,需要单独安装。有了它,你就可以用Git来管理那些大的二进制文件,而不必担心版本更新导致的Git库爆仓的问题。它使用了一种指针的机制来记录版本信息,同时将实际文件存放到另外一个目录中,在Git克隆的过程中,不会下载所有历史版本,而是根据需要,下载特定的某个版本,默认只下载最新版本。

效率高吗?为什么?

相对于原生的Git管理方式,LFS的方式由于不需要一次性的下载所有历史版本,首次下载速度不会有很大影响。但是由于历史版本还在远端,如果需要切换不同的版本,就会临时下载对应的版本,这样实际上是把下载的过程在时间维度上离散化了。对于不关心历史版本的人来说,降低了下载时长。

具体怎么做

安装

bash
1
2
3
4
5
6
7
8
## mac系统
brew install git-lfs

## ubuntu系统安装
sudo apt install git-lfs

## 当前用户启用lfs(用户级设置)
git lfs install

跟踪/取消跟踪文件

bash
 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

切换版本

和日常的切换版本一样,不需要额外的命令:

bash
1
git checkout <HASH>

在切换版本的时候,.git/lfs/目录下会下载历史版本,同时将工作目录中的内容切换为对应的版本。

疑问

  1. 对于已经处于Git管理的二进制文件,是否可以使用LFS管理?

可以,但使用LFS之前的历史记录不受影响。但使用LFS之后,新的文件版本会被放到LFS中进行管理,后续克隆仓库的时候,只克隆一个版本。

  1. Git服务端支持吗?

现有的服务端软件都支持LFS,只是免费托管的仓库,对LFS的存储空间有限制,例如Github可以免费使用2GB空间。

  1. 为什么LFS没有直接合入Git主线,而要用插件的方式单独安装

具体原因不详,不过小编猜测,LFS的解决方式和Git分布式版本管理的理念不符,因为默认LFS无法离线切换版本,需要联网才行。另外就是如果按照Git的分布式设计理念,其实这个问题无解(既要分布式离线可用,又要库占用的空间小),所以思来想去,还是不要放到主线版本里吧。

参考

上一篇:Git服务器-给gerrit搭建一个LDAP认证服务 下一篇:Git进阶-删除垃圾大文件

【文章不错,鼓励一下】