Workflows

大文件处理工作流

使用 Git LFS、稀疏检出和分包策略管理仓库中的大文件,保持克隆速度和历史可维护性。

适合谁看
  • 要把命令组合成稳定流程的团队成员
  • 需要处理协作顺序和分支边界的人
前置知识
  • 知道 fetch / pull / push / branch 的基本作用
  • 能理解一条分支为什么会分叉
常见风险
  • 照抄流程却没确认当前分支关系
  • 在共享分支上用错整合方式

一句话理解

Git 不适合直接管理大文件(二进制、视频、数据集等)。本工作流通过 Git LFS稀疏检出分包策略,让仓库在包含大文件资源的同时,保持克隆速度、历史可维护性和团队协作效率。

大文件处理工作流对大文件的正确做法是在提交前识别文件大小,将超过阈值的文件移交 LFS,保持仓库轻量且可复现。
准备阶段
检查文件大小配置 .gitattributes安装 Git LFS
期望结果
仓库保持轻量大文件存储在 LFS团队无需额外操作
不要等到仓库肿起来才想起 LFS,初期规划比后期迁移成本低得多。

为什么不直接把大文件放进 Git

# 直接提交大文件的问题
git add dataset.csv      # 100MB
git add model.bin        # 500MB
git add demo-video.mp4   # 50MB

# 后果:
# 1. clone 极慢,新成员入职成本增加
# 2. 历史永远携带这些大文件,即使删除也无法减小体积
# 3. push/pull 带宽消耗大
# 4. CI/CD 拉取代码时间变长

Git LFS 工作流

1. 安装和初始化

# 安装 Git LFS
# macOS
brew install git-lfs

# Ubuntu/Debian
sudo apt-get install git-lfs

# 在仓库中启用
git lfs install

2. 追踪大文件类型

# 追踪所有 PSD 文件
git lfs track "*.psd"

# 追踪特定目录
git lfs track "assets/videos/*"

# 追踪特定文件
git lfs track "data/training-set.zip"

# 查看当前追踪规则
git lfs track

# 提交 .gitattributes(LFS 规则存储在这里)
git add .gitattributes
git commit -m "chore: track large files with LFS"

3. 正常使用

# 添加大文件(Git LFS 自动处理)
git add design-v2.psd
git commit -m "design: add new mockup"

# 推送时 LFS 对象单独上传
git push origin main
# Uploading LFS objects: 100% (5/5), 150 MB | 10 MB/s, done

4. 迁移已有大文件到 LFS

# 安装 git-lfs-migrate
# 把历史中的大文件迁移到 LFS(改写历史)
git lfs migrate import --include="*.psd,*.zip,*.mp4" --everything

# 只迁移某个分支
git lfs migrate import --include="*.bin" --include-ref=main

# 推送(需要 force push)
git push --force-with-lease origin main

稀疏检出配合(针对大仓库)

# 只克隆最近一层历史
git clone --depth 1 --filter=blob:none https://github.com/org/large-repo.git

cd large-repo

# 启用稀疏检出
git sparse-checkout init --cone

# 只检出你需要的目录
git sparse-checkout set src/ docs/ scripts/

# 添加更多目录
git sparse-checkout add tests/

# 查看当前检出范围
git sparse-checkout list

分包策略

方案 A:代码与大文件完全分离

project-code/        ← 纯代码仓库,轻量
  src/
  tests/
  docs/

project-assets/      ← 大文件仓库,用 LFS
  images/
  videos/
  models/

方案 B:子模块引用

# 主仓库
cd project-code
git submodule add https://github.com/org/project-assets.git assets

# 克隆时包含子模块
git clone --recurse-submodules https://github.com/org/project-code.git

方案 C:Monorepo + 路径过滤

# 只克隆你需要的目录(配合 sparse-checkout)
git clone --filter=blob:none --no-checkout https://github.com/org/monorepo.git
cd monorepo
git sparse-checkout init --cone
git sparse-checkout set packages/frontend
git checkout

大文件审查清单

# 检查仓库中最大的文件
git rev-list --objects --all | \
  git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
  awk '$1 == "blob" {print $3, $4}' | \
  sort -rn | \
  head -20

# 检查哪些提交引入了大文件
git log --all --format="%H %s" | \
  while read hash msg; do
    size=$(git diff-tree -r -c -M --no-commit-id $hash | \
      awk '{print $4}' | \
      xargs git cat-file -s 2>/dev/null | \
      awk '{sum+=$1} END {print sum}')
    echo "$size $hash $msg"
  done | \
  sort -rn | \
  head -20

团队规范建议

提交前检查文件大小

# .git/hooks/pre-commit
#!/bin/sh
max_size=$((10 * 1024 * 1024))  # 10MB

staged_files=$(git diff --cached --name-only --diff-filter=ACM)
for file in $staged_files; do
  size=$(git cat-file -s :"$file" 2>/dev/null || echo 0)
  if [ "$size" -gt "$max_size" ]; then
    echo "Error: $file is larger than 10MB ($size bytes)"
    echo "Please use Git LFS for large files."
    exit 1
  fi
done

.gitattributes 模板

# 图片
*.psd filter=lfs diff=lfs merge=lfs -text
*.ai filter=lfs diff=lfs merge=lfs -text
*.sketch filter=lfs diff=lfs merge=lfs -text

# 音视频
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.mov filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.mp3 filter=lfs diff=lfs merge=lfs -text

# 数据集和模型
*.zip filter=lfs diff=lfs merge=lfs -text
*.tar.gz filter=lfs diff=lfs merge=lfs -text
*.bin filter=lfs diff=lfs merge=lfs -text
*.onnx filter=lfs diff=lfs merge=lfs -text
*.pkl filter=lfs diff=lfs merge=lfs -text

# 文档
*.pdf filter=lfs diff=lfs merge=lfs -text

最佳实践总结

  1. 预防优于修复:在仓库初始化时就配置 LFS,不要等到大文件已经污染历史
  2. 10MB 红线:普通文件超过 10MB 就应该考虑 LFS
  3. 代码与大文件分离:尽可能把大文件放在独立的仓库或子模块中
  4. 教育团队:确保所有人知道如何正确使用 LFS,否则大文件仍可能被直接提交
  5. 监控仓库体积:定期运行检查脚本,发现体积异常增长及时处理
  6. CI/CD 适配:确保 CI 环境安装了 git-lfs,否则 checkout 会失败

注意事项

  1. Git LFS 有带宽和存储配额限制(GitHub/GitLab 免费额度有限)
  2. LFS 文件不会出现在普通 clone 中,需要 git lfs pullGIT_LFS_SKIP_SMUDGE=1
  3. 迁移历史到 LFS 需要改写历史(force push),影响所有协作者
  4. 某些 Git 托管平台对 LFS 的支持程度不同,需要确认平台兼容性
  5. fork 的仓库需要单独配置 LFS,不会自动继承主仓库的 LFS 对象