本文主要介绍 Git LFS(Large File Storage)的工作方式、常用客户端命令,以及在 Gitea 上开启 LFS 时的 app.ini 要点。

Git 对大体积二进制文件不友好:每次变更都会在对象库中留下难以增量压缩的 blob,导致 clone/fetch 变慢、仓库膨胀。LFS 用指针文件进入 Git 历史,实体文件放到独立 LFS 存储,由客户端在 checkout/push 时透明上下传。

核心概念

说明
指针文件仓库中保存的小文本,指明 OID、大小等
LFS 存储实际大文件所在位置(本地盘、MinIO、云存储等)
钩子 / smudge-clean在 add/checkout 时在指针与实体间转换
服务端托管平台需开启 LFS API(GitHub/GitLab/Gitea 等)

工作流示意:

git add 大文件
  → LFS 识别 track 规则
  → 实体上传 LFS 存储,Git 只提交指针
git checkout / clone
  → 按需从 LFS 拉取实体(可 skip smudge 只留指针)

适合 / 不适合

适合:设计源文件、高清媒体、大型压缩包、数据集、少改动的二进制产物等。

不适合:源码与文本配置、频繁小改的小文件(LFS 增加链路复杂度,收益小)。

客户端常用命令

安装与环境

git lfs install
git lfs version
git lfs env

install 会在本机配置 Git 过滤器与钩子,每个开发者机器通常都需要执行一次。

跟踪规则

git lfs track "*.psd"
git lfs track "*.mp4"
git lfs track "assets/**"
git lfs track
git lfs ls-files

track 会改写 .gitattributes,需一并提交:

git add .gitattributes
git commit -m "chore: configure Git LFS tracking"

.gitattributes 片段示例:

*.psd filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text

日常提交与同步

git add .
git commit -m "Add large assets"
git push origin main

git lfs status
git lfs pull
git lfs push origin main

多数情况下 git push/git pull 已足够;网络或权限异常时可显式 git lfs push/pull

维护与迁移

git lfs ls-files --all
git lfs ls-files --long
git lfs prune
git lfs fetch --all
git lfs push --all origin

# 将已在 Git 历史中的文件迁入 LFS(会改写历史,需团队评估)
git lfs migrate import --include="*.psd,*.ai" --everything

克隆策略

git clone <repo-url>

# 只拉指针,稍后再拉实体
GIT_LFS_SKIP_SMUDGE=1 git clone <repo-url>
git lfs pull --include="path/to/file.psd"

可选全局参数

git config --global lfs.dialtimeout 300
git config --global lfs.concurrenttransfers 8

按网络与磁盘能力调整,勿盲目加大并发。

初始化示例

git lfs install
git lfs track "*.psd"
git lfs track "assets/videos/*.mp4"
git add .gitattributes
git commit -m "Configure Git LFS tracking"
git add large-file.psd
git commit -m "Add design file"
git push origin main

推送成功后,在支持 LFS 的托管 UI 中,对象详情或仓库「LFS」页应能看到对应文件(Gitea 见下节)。

Gitea 服务端配置

配置文件一般为 custom/conf/app.ini(或发行包约定的 conf 路径)。完整项见 app.example.ini

[server] 开启 LFS

[server]
LFS_START_SERVER = true
LFS_ALLOW_PURE_SSH = true
; 务必自行生成,勿使用空值或公开示例
LFS_JWT_SECRET = <generate-a-secret>
LFS_MAX_FILE_SIZE = 0
LFS_LOCKS_PAGING_NUM = 50
LFS_MAX_BATCH_SIZE = 0
LFS_HTTP_AUTH_EXPIRY = 24h

LFS_MAX_FILE_SIZE = 0 表示不在此限制单文件大小(仍可能受反代/磁盘约束)。生产建议设明确上限。

[lfs] 与 [lfs_client]

[lfs]
STORAGE_TYPE = local
PATH = /data/git/lfs
SERVE_DIRECT = false
; STORAGE_TYPE = minio 时还可配 MINIO_* / SERVE_DIRECT 等,见官方示例

[lfs_client]
BATCH_SIZE = 20
BATCH_OPERATION_CONCURRENCY = 8

STORAGE_TYPElocal 外可对接 MinIO、Azure Blob 等(版本以当前 Gitea 文档为准)。改完后重启 Gitea 使配置生效。

验证

  • 客户端 git lfs env 指向的 endpoint 为该 Gitea。
  • 推送 LFS 对象后,在仓库 Web UI 中文件信息含 LFS 标识,仓库设置中有 LFS 对象列表(历史截图资产若需上站,迁到 assets/posts/ 再链)。

注意事项

  • 全员安装 LFS;未装 LFS 的机器可能只看到指针文本或提交异常。
  • 关注托管侧 LFS 存储配额 与备份(LFS 对象不在普通 git bundle 的同一路径上)。
  • migrate import 会改写历史,流程类似历史瘦身,需 force push 与协作约定。
  • 与「误提交大文件后 untrack」不同:LFS 是从一开始就避免大 blob 进 Git 对象库。

参考资料