解决 Git LFS 成本爆炸与虚幻引擎资产冲突的 Lore VCS 迁移指南
TuBrief 편집팀
2026년 7월 14일
0
Computing/Software원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
커뮤니티의 다른 글
댓글 (0)
Log in to leave a comment
아직 작성된 글이 없습니다
원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
Log in to leave a comment
아직 작성된 글이 없습니다
当项目规模扩大时,Git LFS 就会变成一场灾难。修改几行源代码只需瞬间,但一旦开始掺杂千兆字节(GB)级的艺术资产,每次提交都会让鼠标指针转上半天沙漏。由于 LFS 将大文件整块复制并堆积的迟钝结构,存储库容量很快就会超过数太字节(TB),带宽账单上的数字也会变得触目惊心。
Epic Games 开源的 Lore 将二进制文件放在首位。它使用 FastCDC 方式将文件切分为块并消除重复,从而显著降低了包体积和传输带宽。即使是缺乏 DevOps 专业人员的小型团队,也能立即应用本文总结的 Lore 实战迁移与优化方法。
没有必要非要抛弃现有 Git 存储库中积累的源代码提交历史。将轻量级的代码保留在 Git 中,仅将笨重的二进制资产分离到 Lore 存储库中,是一种切实可行的混合策略。
下面的脚本识别出 Git LFS 追踪的文件列表,创建对称的目录结构,并对照副本的 SHA-256 哈希值,确保在不丢失数据的情况下迁移到 Lore。
`bash
#!/usr/bin/env bash
set -euo pipefail
GIT_REPO_DIR="HOME/projects/my-game-lore"
LORE_SERVER_URL="lore://127.0.0.1:41337/my-project"
echo "[1/5] 初始化 Lore 存储库及远程绑定..."
if [ ! -d "LORE_REPO_DIR"
cd "LORE_SERVER_URL"
else
cd "$LORE_REPO_DIR"
fi
echo "[2/5] 收集 Git LFS 追踪文件列表..."
cd "(git lfs ls-files -n | grep -E ".(uasset|umap|fbx|png|psd)$" || true)
if [ -z "$LFS_FILES" ]; then
echo "没有需要迁移的 LFS 文件。"
exit 0
fi
echo "[3/5] 复制文件并生成验证清单..."
echo "filepath" ]; then
dest_dir="(dirname "dest_dir"
cp -p "LORE_REPO_DIR/(openssl dgst -sha256 "$filepath" | awk '{print 2}')
echo "filepath:LORE_REPO_DIR/.lore_migration_manifest"
fi
done
echo "[4/5] 解除 Git LFS 追踪并暂存到 Lore..."
cd "LFS_FILES" | while read -r filepath; do
git rm --cached "$filepath"
done
sed -i.bak -E 's/filter=lfs diff=lfs merge=lfs//g' .gitattributes
cd "LFS_FILES" | while read -r filepath; do
lore stage "$filepath"
done
lore commit -m "Migration: Transfer heavy assets from Git LFS to Lore"
lore push
echo "[5/5] 数据完整性验证..."
lore repository verify state
lore repository verify fragment
if [ -f ".lore_migration_manifest" ]; then
migration_errors=0
while IFS=":" read -r file sha; do
if [ -f "(openssl dgst -sha256 "$file" | awk '{print 2}')
if [ "sha" != "$current_hash" ]; then
echo "检测到受损文件: ((migration_errors + 1))
fi
fi
done < .lore_migration_manifest
if [ $migration_errors -eq 0 ]; then
echo "迁移完成。所有数据已 100% 完整恢复。"
rm .lore_migration_manifest
else
echo "验证失败: 有 $migration_errors 个文件的完整性存在问题。"
exit 1
fi
fi
`
打开终端,将上述内容保存为 migrate.sh。使用 chmod +x migrate.sh 命令赋予执行权限,然后根据你的本地路径修改变量后即可运行。
完成此操作后,远程云端 LFS 的存储使用量将立即减少。根据 Epic Games 的内部应用案例,通过这种块级去重技术,可将基础设施维护成本降低 50% 左右。
每个构建周期都重新下载数百 GB 的完整游戏资产的流水线,是摧毁网卡和磁盘 I/O 的罪魁祸首。为了缩短构建时间,Lore 支持基于虚拟文件系统的按需加载(On-demand Hydration)。
在初始克隆阶段,它仅以空壳形式复制元数据结构链和目录树,当编译器在烹饪(Cook)过程中读取实际资产时,再动态流式传输所需的二进制分块并填入磁盘。
`yaml
name: Game Project On-Demand Production Build
on:
push:
branches: [ release-candidate ]
env:
LORE_SERVER: "lore://10.0.1.50:41337/game-depot"
SHARED_STORE_PATH: "/var/lib/lore_shared_chunk_store"
WORKSPACE_PATH: "game_build_workspace"
jobs:
assemble-assets:
runs-on: self-hosted
steps:
- name: 准备持久化共享存储
run: |
if [ ! -d "{{ env.SHARED_STORE_PATH }}"
sudo chmod 777 "{{ env.SHARED_STORE_PATH }}"
fi
- name: 经由共享缓存进行稀疏裸克隆(Sparse Bare Clone)
run: |
lore clone \
--bare \
--use-shared-store \
--shared-store-path "${{ env.SHARED_STORE_PATH }}" \
"${{ env.LORE_SERVER }}" \
"${{ env.WORKSPACE_PATH }}"
- name: 通过视图过滤器排除不必要的过场动画源文件
run: |
cd "${{ env.WORKSPACE_PATH }}"
echo "+ /SourceCode/" > .lore/view
echo "+ /Config/" >> .lore/view
echo "+ /Content/Core_Assets/" >> .lore/view
echo "- /Content/Cinematic_RAW/" >> .lore/view
- name: 仅将必要的分块同步到本地磁盘
run: |
cd "${{ env.WORKSPACE_PATH }}"
lore sync
- name: 执行虚幻引擎 Cooker
run: |
cd "${{ env.WORKSPACE_PATH }}"
./RunUAT.sh BuildCookRun \
-project="$(pwd)/GameProject.uproject" \
-platform=Win64 \
-clientconfig=Development \
-cook -stage -pak -archive
`
如果在构建专用服务器上准备好 /var/lib/lore_shared_chunk_store 这样的持久化缓存,效果会达到极致。通过 lore clone --bare 命令快速获取索引信息后,在 .lore/view 过滤器文件中保留必要路径,然后执行 lore sync。建立这种结构后,传输到构建节点的流量将比平时减少 85% 以上,整体构建时间平均缩短约 30%。
虚幻引擎的 .uasset 或关卡地图文件等二进制资产,不像文本代码那样可以在主分支中自动合并。如果两名艺术家同时修改同一个资产,就会发生事故:后推送的人覆盖了前一个人的工作,导致工作丢失或时间线错乱。
Lore 直接提供了锁定(Lock)功能,基于远程服务器的不可变账本进行排他性控制。
`bash
lore lock acquire Content/Characters/HeroMesh.uasset --branch main
lore lock status Content/Characters/HeroMesh.uasset
lore lock query --branch main --owner developer_artist_03
lore lock release Content/Characters/HeroMesh.uasset --branch main
`
必须建立规则,要求艺术家在触碰文件之前使用 lore lock acquire 命令获取锁定。修改完成后,如果提交和推送已成功反映到远程,则使用 lore lock release 解锁,交给下一个操作者。
如果策划和艺术家对终端命令感到不习惯,可以将相应路径与 Anchorpoint 等桌面 GUI 工具关联,只需鼠标右键点击即可执行这些锁定命令,从而构建良好的环境。
应根据工作环境的规格调整客户端设置,以防止文件 I/O 瓶颈。
--direct-file-write 和 --direct-file-io 标志以直接写入磁盘,并增加垃圾回收调度间隔,防止工作时出现突发的磁盘占位现象。参考 Lore 架构决策会议(ADR-00016)结果,在效率方面,将 Zstandard Level 6 规格设置为默认压缩引擎最为均衡。
| 压缩算法种类 | 数据最终压缩率 (%) | 压缩运算速度 (MiB/s) | 解压速度 (MiB/s) | 可移植性及特点 |
|---|---|---|---|---|
| LZ4 Default | 47.6% | 718.7 | 2494.5 | 速度快,但存储空间浪费严重 |
| Zstd Level 1 | 34.5% | 602.0 | 1363.1 | 速度与空间保留的合理折中点 |
| Zstd Level 6 (推荐) | 28.9% | 136.5 | 1284.9 | 在节省空间与处理效率之间保持最佳平衡 |
| Oodle Kraken 3 (Fast) | 28.2% | 95.6 | 1413.1 | 需要 Epic Games 独家 Oodle 依赖库 |
| Oodle Kraken 6 (原有默认) | 23.9% | 2.2 | 1312.6 | 千兆字节级迁移时速度严重下降 |
曾经常用的 Oodle Kraken Level 6 在后端序列化过程中,压缩处理速度下降到每秒 2.2 MiB,这是导致艺术家下班前提交等待时间延长的主要原因。
相比之下,Zstd Level 6 在提供媲美 Oodle Kraken 6 压缩率的同时,本地块压缩速度达到 136.5 MiB/s,快了约 62 倍。如果海外分公司或居家办公人员较多,带宽干扰严重,建议考虑构建双层服务器拓扑,在本地网络内配置代理边缘缓存节点。