1. 背景
项目中通常会有一些比较大的文件(eg: .a,.mp3,framework...),导致 git 仓库过大,导致出现了一系列问题,包括但不限于 git clone 失败、git大小超出限制、服务器资源浪费等。
2. 什么是 git lfs
An open source Git extension for versioning large files
Git Large File Storage (LFS) replaces large files such as audio samples, videos, datasets, and graphics with text pointers inside Git, while storing the file contents on a remote server like GitHub.com or GitHub Enterprise.
使用了 git lfs 之后,在 commit 中不再直接跟踪文件,而是追踪文件的在lfs服务商的一个对象标识
,而且此类文件在进行 pull&push 的时候是另外的文件服务进行上传和下载,效率相对 git commit 的题上传和下载速度大大提升。
3.使用
3.1 安装
Homebrew: brew install git-lfs
MacPorts: port install git-lfs
在安装之后必须要执行一次 git lfs install
。可在任意目录下执行,这里会修改一些 global config。
3.2 对该仓库以后的大文件进行管理
1. 初始化
git lfs install
该命令执行完成后,会在 .git/hooks 下添加相关的钩子,还会在 .git 目录下创建 lfs 文件夹,用以存储 lfs 相关的文件。
2. 选择要用 lfs 追踪的文件
git lfs track "*.svg"
git lfs track "AABB.zip"
这一步如果第一次使用,会创建 .gitattributes 文件,记得 git add 这个文件
3. 像平时那样进行 commit、push、pull。 无需额外操作,lfs 相关的操作会由hook进行处理。
4. 查看 lfs 追踪的文件列表
git lfs ls-files
5. 取消文件的追踪
git lfs untrack "*.svg"
git lfs untrack "AABB.zip"
5. 关闭 lfs
git lfs uninstall
3.2 对已经存在仓库的大文件进行管理
针对已有仓库的大文件进行管理的话,需要使用到 git lfs migrate
命令进行迁移。
暂时无法在飞书文档外展示此内容
1. 对已提交本地,但还没有推到远端的进行迁移
git lfs migrate import --include="*.jar"
这个命令会使已经存在的 commit 发生一些变化,如下图所示。
2. 针对已经提交到远端的,需要增加一些额外参数
git lfs migrate import --include="*.zip" --include-ref=refs/heads/dev
同样的,这个命令也会导致现有的 commit 发生变化,推送时需要强制推送,此时一定要谨慎。
3. 迁移后清理 .git 目录
上面的 1 和 2 已经将预先存在的 git 对象转换为 lfs 对象。但是,常规对象仍保留在 .git 目录中。这些最终将由 git 清理,但要立即清理它们,请运行:
- 清理不可达的 reflog 条目
git reflog expire --expire-unreachable=now --all
- 执行垃圾回收并立即删除未引用对象
git gc --prune=now
4 优缺点
1. 优点
- 将文件存储在文件存储系统中,大大减小了仓库的大小
- 对大文件存储做了优化,能更好的控制文件版本,支持对文件的增量存储,进一步减小了存储空间的消耗
- 使用 git lfs 后,传输的是文件指针,文件仅在需要是才被下载,提高了git的使用效率
2. 缺点
- 需要确保团队所有成员都安装并配置了 git lfs,并且git 版本不能过低
- 对于频繁更改的大文件, git lfs 的性能会受到影响
- 某些IDE或者编辑器可能没有集成 git lfs,需要使用额外的配置或者安装,或者使用终端
5 最佳实践
- 确保团队的每个成员都安装了 git lfs,并且有一定的了解
- 遵循相同的工作流程和规范
- 确保不意外的将大文件添加到仓库中,需要 .gitignore 文件配合使用
- 定期检查不再需要的文件和历史记录 git lfs prune
附加内容
一个小小的脚本,可以筛选项目内单个文件大小过大的文件列表。并且在前面追加 git lfs track
命令,复制下来可以执行。
# -*- coding: utf-8 -*-
import os
import sys
import argparse
# 存储大文件信息的列表
big_files = []
# 忽略的目录
ignore_dirs = {'Pods', 'build', 'node_modules'}
def get_file_size_mb(file_path):
"""获取文件大小(MB)"""
return os.path.getsize(file_path) / (1024 * 1024)
def find_big_files(path, size_threshold):
"""递归查找大文件"""
for file_name in os.listdir(path):
if file_name.startswith('.'):
continue
file_path = os.path.join(path, file_name)
if os.path.isdir(file_path):
# 跳过忽略的目录
if file_name in ignore_dirs:
continue
find_big_files(file_path, size_threshold)
elif os.path.isfile(file_path):
file_size = get_file_size_mb(file_path)
if file_size > size_threshold:
big_files.append({
'path': file_path,
'size': file_size
})
def main():
# 设置命令行参数
parser = argparse.ArgumentParser(description='查找目录下大于指定大小的文件')
parser.add_argument('path', help='要搜索的目录路径')
parser.add_argument('-a', '--action', help='要在路径前面拼接的字符串')
parser.add_argument('-s', '--size', type=float, default=5, help='文件大小阈值(MB),默认为5MB')
args = parser.parse_args()
# 检查目录是否存在
if not os.path.isdir(args.path):
print(f'错误:目录 {args.path} 不存在')
sys.exit(1)
# 执行搜索
find_big_files(args.path, args.size)
# 按文件大小降序排序
big_files.sort(key=lambda x: x['size'], reverse=True)
# 输出结果
print(f'目录下 {args.path}\n找到 {len(big_files)} 个大于 {args.size}MB 的文件:\n')
for file in big_files:
sub_path = file["path"].replace(args.path, "")
if sub_path.startswith("/"):
sub_path = sub_path[1:]
print(f'{file["size"]:.2f}MB\t{sub_path} {file["path"]}')
if args.action is None:
return
print('\n拼接action之后的路径')
for file in big_files:
sub_path = file["path"].replace(args.path, "")
if sub_path.startswith("/"):
sub_path = sub_path[1:]
print(f'{args.action} {sub_path}')
if __name__ == '__main__':
main()
# usage: finderBigfiles.py [-h] [-a ACTION] [-s SIZE] path
# 查找目录下大于指定大小的文件
# positional arguments:
# path 要搜索的目录路径
# options:
# -h, --help show this help message and exit
# -a, --action ACTION 要在路径前面拼接的字符串
# -s, --size SIZE 文件大小阈值(MB),默认为5MB
可以以以下这种方式执行
python3 finderBigfiles.py ~/Documents/workspace/APP-iOS -a 'git lfs track '
或者
python3 finderBigfiles.py -a 'git lfs track ' ~/Documents/workspace/APP-iOS