TuBrief
구독 채널
비디오
커뮤니티

Lore VCS Migration Guide: Solving Git LFS Cost Explosions and Unreal Asset Conflicts

TuBrief 편집팀
2026년 7월 14일
0
Computing/Software

원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.

English한국어Español中文العربيةDeutschFrançaisPortuguêsहिन्दीРусскийBahasa Indonesia日本語

관련 영상

Git Can’t Handle Games… So Epic Built Lore7:44

Git Can’t Handle Games… So Epic Built Lore

Better Stack

커뮤니티의 다른 글

사내 시스템에 llm api 붙일 때 마주하는 현실적인 한계와 대응법

2026년 9월 13일

레거시 백엔드에 GPT-6 Astra 붙일 때 예산 승인과 보안 통과를 먼저 끝내는 법이 있습니다

2026년 9월 13일

에이전트끼리 대화하다 6천만 원 청구서가 나오는 이유

2026년 9월 13일

사내 RAG 벡터 검색에 Okta 권한 필터를 직접 거는 방법

2026년 9월 13일

브라우저 에이전트에게 내 구글 계정을 통째로 넘기면 안 되는 이유

2026년 9월 12일

Apple Won the AI Race

2026년 9월 12일

댓글 (0)

Log in to leave a comment

아직 작성된 글이 없습니다

© 2026 . All rights reserved.

TuBrief
구독 채널
비디오
커뮤니티
로그인

Lore VCS Migration Guide: Solving Git LFS Cost Explosions and Unreal Asset Conflicts

As projects scale, Git LFS turns into a disaster. Fixing a few lines of source code is instantaneous, but once multi-gigabyte art assets start getting mixed in, you’re left staring at an hourglass for tens of seconds on every commit. Because of the sluggish structure of LFS, which involves copying and storing entire large files, repository sizes quickly exceed terabytes, leading to terrifying numbers on your bandwidth invoices.

Lore, open-sourced by Epic Games, treats binary files as a first-class citizen. It uses the FastCDC method to split files into blocks and eliminate duplicates, drastically reducing package sizes and transfer bandwidth. We have compiled practical Lore migration and optimization methods that even small teams without dedicated DevOps personnel can implement immediately.


1. Gradually Migrating from Git LFS to Lore

There is no need to discard the source code commit history accumulated in your existing Git repository. A hybrid strategy is practical: leave light code in Git as is, and move only the heavy binary assets to a Lore repository.

The script below identifies the list of files tracked by Git LFS, creates a symmetric directory structure, and migrates them to Lore without data loss by comparing the SHA-256 hashes of the copies.

`bash
#!/usr/bin/env bash
set -euo pipefail

GIT_REPO_DIR="HOME/projects/my−game−git"LOREREPODIR="HOME/projects/my-game-git" LORE_REPO_DIR="HOME/projects/my−game−git"LORER​EPOD​IR="HOME/projects/my-game-lore"
LORE_SERVER_URL="lore://127.0.0.1:41337/my-project"

echo "[1/5] Initializing Lore repository and binding remote..."
if [ ! -d "LOREREPODIR"];thenmkdir−p"LORE_REPO_DIR" ]; then mkdir -p "LORER​EPOD​IR"];thenmkdir−p"LORE_REPO_DIR"
cd "LOREREPODIR"lorerepositorycreate"LORE_REPO_DIR" lore repository create "LORER​EPOD​IR"lorerepositorycreate"LORE_SERVER_URL"
else
cd "$LORE_REPO_DIR"
fi

echo "[2/5] Collecting Git LFS tracked file list..."
cd "GITREPODIR"LFSFILES=GIT_REPO_DIR" LFS_FILES=GITR​EPOD​IR"LFSF​ILES=(git lfs ls-files -n | grep -E ".(uasset|umap|fbx|png|psd)$" || true)

if [ -z "$LFS_FILES" ]; then
echo "No LFS files to migrate."
exit 0
fi

echo "[3/5] Copying files and generating manifest for verification..."
echo "LFSFILES"∣whileread−rfilepath;doif[−f"LFS_FILES" | while read -r filepath; do if [ -f "LFSF​ILES"∣whileread−rfilepath;doif[−f"filepath" ]; then
dest_dir="LOREREPODIR/LORE_REPO_DIR/LORER​EPOD​IR/(dirname "filepath")"mkdir−p"filepath")" mkdir -p "filepath")"mkdir−p"dest_dir"
cp -p "filepath""filepath" "filepath""LORE_REPO_DIR/filepath"sourcehash=filepath" source_hash=filepath"sourceh​ash=(openssl dgst -sha256 "$filepath" | awk '{print 2}') echo "filepath:sourcehash">>"source_hash" >> "sourceh​ash">>"LORE_REPO_DIR/.lore_migration_manifest"
fi
done

echo "[4/5] Unlinking Git LFS and staging to Lore..."
cd "GITREPODIR"echo"GIT_REPO_DIR" echo "GITR​EPOD​IR"echo"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 "LOREREPODIR"echo"LORE_REPO_DIR" echo "LORER​EPOD​IR"echo"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] Verifying data integrity..."
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 "file"];thencurrenthash=file" ]; then current_hash=file"];thencurrenth​ash=(openssl dgst -sha256 "$file" | awk '{print 2}') if [ "sha" != "$current_hash" ]; then
echo "Corrupted file detected: file"migrationerrors=file" migration_errors=file"migratione​rrors=((migration_errors + 1))
fi
fi
done < .lore_migration_manifest

if [ $migration_errors -eq 0 ]; then
    echo "Migration complete. All data recovered with 100% integrity."
    rm .lore_migration_manifest
else
    echo "Verification failed: $migration_errors file(s) have integrity issues."
    exit 1
fi

fi

`

Open your terminal and save the above content as migrate.sh. Grant execution permissions with chmod +x migrate.sh, then modify the variables to match your local paths and execute it.

Once this task is finished, your remote cloud LFS storage usage will drop immediately. According to Epic Games' own adoption case, this block-level deduplication technology can reduce infrastructure maintenance costs by up to 50%.


2. Applying On-demand Hydration in CI/CD Pipelines

Pipelines that re-download hundreds of gigabytes of full game assets every build cycle are the main culprits behind destroying network cards and disk I/O. To shorten build times, Lore supports On-demand Hydration based on a virtual file system.

During the initial clone phase, only the metadata structure chain and directory tree are replicated in a 'shell' form; only the binary chunks needed when the compiler reads the actual assets during the cooking process are dynamically streamed and populated on the disk.

`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: Preparing Persistent Shared Store
run: |
if [ ! -d "env.SHAREDSTOREPATH"];thensudomkdir−p"{{ env.SHARED_STORE_PATH }}" ]; then sudo mkdir -p "env.SHAREDS​TOREP​ATH"];thensudomkdir−p"{{ env.SHARED_STORE_PATH }}"
sudo chmod 777 "env.SHAREDSTOREPATH"loreshared−storecreate"{{ env.SHARED_STORE_PATH }}" lore shared-store create "env.SHAREDS​TOREP​ATH"loreshared−storecreate"{{ env.SHARED_STORE_PATH }}"
fi

  - name: Sparse Bare Clone via Shared Cache
    run: |
      lore clone \
        --bare \
        --use-shared-store \
        --shared-store-path "${{ env.SHARED_STORE_PATH }}" \
        "${{ env.LORE_SERVER }}" \
        "${{ env.WORKSPACE_PATH }}"

  - name: Excluding unnecessary cinematic sources via View Filter
    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: Synchronizing only essential chunks to local disk
    run: |
      cd "${{ env.WORKSPACE_PATH }}"
      lore sync

  - name: Running Unreal Engine Cooker
    run: |
      cd "${{ env.WORKSPACE_PATH }}"
      ./RunUAT.sh BuildCookRun \
        -project="$(pwd)/GameProject.uproject" \
        -platform=Win64 \
        -clientconfig=Development \
        -cook -stage -pak -archive

`

Setting up a persistent cache store like /var/lib/lore_shared_chunk_store on your build-dedicated server will maximize the effect. After quickly pulling only index information with lore clone --bare, leave only the necessary paths in the .lore/view filter file and run lore sync. Establishing this structure can eliminate over 85% of traffic sent to build nodes and shorten total build time by an average of 30%.


3. Preventing Asset Conflicts with File Locking Systems

Binary assets like Unreal Engine's .uasset or level map files cannot be automatically merged in the main branch like text code. If two artists modify the same asset simultaneously, accidents occur where the person who pushes later overwrites the predecessor's work, or the timeline becomes corrupted.

Lore provides a lock feature that performs exclusive control based on an immutable ledger on the remote server.

`bash

Requesting exclusive editing rights for a specific binary character model file

lore lock acquire Content/Characters/HeroMesh.uasset --branch main

Checking the lock ownership status of resources under a specific folder

lore lock status Content/Characters/HeroMesh.uasset

Searching for all files locked by a specific worker in the remote repository

lore lock query --branch main --owner developer_artist_03

Releasing authority after completing work and pushing

lore lock release Content/Characters/HeroMesh.uasset --branch main
`

You must establish a rule where artists must occupy a lock with the lore lock acquire command before touching a file. Once modifications are finished and the commit/push is safely reflected on the remote, use lore lock release to unlock it for the next worker.

If planners and artists find terminal commands awkward, you can configure the environment so that these lock commands are executed by right-clicking in a desktop GUI tool like Anchorpoint, by linking the paths.


4. Cache Tuning Guide by Hardware Specs

Adjust client settings according to your workstation specifications to prevent file I/O bottlenecks.

Local Client Tuning by Worker PC Specs

  • High-performance System (NVMe SSD, 32GB RAM or more, multi-core CPU): Allows memory-mapped direct operations via OS virtual memory mapping techniques. To eliminate synchronization latency, expand the maximum number of parallel download connection threads and maintain long disk cache retention periods.
  • Entry-level and Artist Systems (SATA SSD or HDD, 16GB RAM or less): To prevent engine crashes due to memory exhaustion, disable memory-mapped methods. Enable the --direct-file-write and --direct-file-io flags for direct disk writing, and increase the garbage collection schedule interval to prevent unexpected disk preemption during work.

Performance Analysis by Compression Algorithm Selection

Referring to the Lore Architecture Decision Records (ADR-00016), setting the Zstandard Level 6 standard as the default compression engine offers the best balance in terms of efficiency.

Compression Algorithm Type Final Data Compression Ratio (%) Compression Speed (MiB/s) Decompression Speed (MiB/s) Portability & Characteristics
LZ4 Default 47.6% 718.7 2494.5 Fast speed but high storage capacity waste
Zstd Level 1 34.5% 602.0 1363.1 A decent compromise between speed and capacity preservation
Zstd Level 6 (Recommended) 28.9% 136.5 1284.9 Maintains optimal processing efficiency vs. space saving
Oodle Kraken 3 (Fast) 28.2% 95.6 1413.1 Requires proprietary Epic Games Oodle library
Oodle Kraken 6 (Previous default) 23.9% 2.2 1312.6 Severe speed degradation when transferring in gigabytes

The previously popular Oodle Kraken Level 6 saw compression processing speeds drop to the 2.2 MiB/s level during backend serialization, which was a primary cause of artists waiting to commit before leaving work.

On the other hand, Zstd Level 6 provides a compression ratio close to Oodle Kraken 6 while having a local chunk block compression speed of 136.5 MiB/s, which is approximately 62 times faster. If you have many overseas branches or remote workers and suffer from bandwidth interference, consider configuring a 2-tier server topology by setting up proxy edge cache nodes within your local network.