دليل ترحيل Lore VCS لحل مشكلات تكاليف Git LFS وتضارب أصول Unreal Engine
TuBrief 편집팀
2026년 7월 14일
0
Computing/Software원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
커뮤니티의 다른 글
댓글 (0)
Log in to leave a comment
아직 작성된 글이 없습니다
원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
Log in to leave a comment
아직 작성된 글이 없습니다
عندما ينمو المشروع، يتحول Git LFS إلى كارثة حقيقية. إصلاح بضعة أسطر من التعليمات البرمجية يستغرق لحظات، ولكن بمجرد أن تبدأ أصول الفن التي تقاس بالجيجابايت في الاختلاط، تدور الساعة الرملية لعشرات الثواني مع كل عملية دفع (Commit). وبسبب البنية البطيئة لـ LFS التي تعتمد على نسخ الملفات الكبيرة بالكامل، تتجاوز مساحة التخزين في المستودع التيرابايت في وقت قصير، وتظهر أرقام مرعبة في فواتير النطاق الترددي (Bandwidth).
صممت شركة Epic Games أداة Lore مفتوحة المصدر للتعامل مع الملفات الثنائية (Binary files) كأولوية قصوى. فهي تستخدم طريقة FastCDC لتقسيم الملفات إلى كتل وإزالة التكرار، مما يقلل بشكل كبير من حجم الحزمة ونطاق النقل الترددي. لقد قمنا بتلخيص طرق الترحيل العملي والتحسين في Lore التي يمكن للفرق الصغيرة، التي تفتقر إلى متخصصي DevOps، تطبيقها على الفور.
ليس من الضروري التخلص من سجل التزامات (Commit history) التعليمات البرمجية المتراكم في مستودع 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 وتجهيز (Staging) 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
`
افتح المحطة الطرفية (Terminal) واحفظ المحتوى أعلاه باسم migrate.sh. بعد منح إذن التنفيذ باستخدام أمر chmod +x migrate.sh وتعديل المتغيرات لتناسب مساراتك المحلية، يمكنك تنفيذه.
بمجرد الانتهاء من هذه المهمة، سينخفض استخدام تخزين LFS السحابي البعيد على الفور. وفقاً لحالات الاعتماد الفعلية في Epic Games، يمكن لتقنية إزالة تكرار البيانات على مستوى الكتل خفض تكاليف صيانة البنية التحتية بنسبة 50%.
خطوط الأنابيب التي تقوم بتنزيل مئات الجيجابايت من أصول اللعبة بالكامل في كل دورة بناء هي السبب الرئيسي لإتلاف بطاقات الشبكة وإدخال/إخراج القرص. تدعم Lore الاسترداد عند الطلب (On-demand Hydration) القائم على نظام الملفات الافتراضي لتقليل وقت البناء.
في مرحلة الاستنساخ الأولى (Clone)، يتم نسخ سلسلة هيكل البيانات الوصفية وشجرة الدليل فقط كقشرة خارجية، وعندما يقرأ المترجم الأصول الفعلية أثناء عملية الطهي (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: Persistent Shared Store 준비
run: |
if [ ! -d "{{ env.SHARED_STORE_PATH }}"
sudo chmod 777 "{{ env.SHARED_STORE_PATH }}"
fi
- name: Shared Cache를 경유한 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: Unreal Engine 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 في Unreal Engine أو ملفات خريطة المستوى تلقائياً في الفرع الرئيسي مثل تعليمات البرمجية النصية. إذا قام فنانان بتعديل نفس الأصل في وقت واحد، فسيحدث حادث حيث يقوم الفنان الذي قام بالدفع لاحقاً بالكتابة فوق عمل الشخص السابق أو التسبب في تشابك الخط الزمني.
توفر 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، بحيث يمكن تنفيذ أوامر القفل هذه بنقرة زر الماوس الأيمن.
يجب ضبط إعدادات العميل وفقاً لمواصفات بيئة العمل لمنع اختناقات الإدخال/الإخراج للملفات.
--direct-file-write و --direct-file-io للكتابة مباشرة على القرص، وقم بزيادة الفاصل الزمني لجدول تجميع القمامة (Garbage Collection) لمنع حدوث ظاهرة احتلال القرص المفاجئة أثناء العمل.بالرجوع إلى نتائج اجتماع تحديد بنية 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 | يتطلب مكتبة Oodle الخاصة بـ Epic Games |
| Oodle Kraken 6 (الافتراضي السابق) | 23.9% | 2.2 | 1312.6 | تنخفض السرعة بشدة عند الترحيل بالجيجابايت |
كان Oodle Kraken Level 6، الذي كان يستخدم بشكل متكرر في الماضي، السبب الرئيسي لإطالة وقت انتظار الفنانين قبل المغادرة، حيث تنخفض سرعة معالجة الضغط أثناء عملية التسلسل (Serialization) في الخلفية إلى مستوى 2.2 MiB في الثانية.
في المقابل، يوفر Zstd Level 6 نسبة ضغط تقترب من Oodle Kraken 6، بينما سرعة ضغط كتل الأجزاء المحلية تصل إلى 136.5 MiB/s، وهي أسرع بحوالي 62 مرة. إذا كان هناك العديد من المكاتب الخارجية أو العاملين عن بعد مما يسبب تداخلاً في النطاق الترددي، ففكر في تكوين طبقة ثانية من طوبولوجيا الخادم لتكوين عقد ذاكرة تخزين مؤقت فرعية (Proxy edge cache) داخل الشبكة المحلية.