همه چیز درباره Git LFS – به زبان ساده


اغلب ما نخستین باری که با LFS در Git مواجه شدیم، در زمان کار روی پروژههای علوم داده بوده است. شاید با خود بپرسید Git خود به اندازه کافی دشوار است، آیا باید یکی دیگر از قابلیتهای آن را نیز یاد بگیریم؟ شاید هم کنجکاو هستید که Git LFS چیست و چرا باید آن را بیاموزید. در این صورت توصیه میکنیم، در ادامه این مقاله با ما همراه باشید تا به پاسخ سؤالهایتان برسید.
ابتدا مقدمه کوتاهی در مورد اهمیت LFS و کاربرد آن بیان میکنیم. تصور کنید مشغول کار روی یک پروژه تحلیل دادههای فیلم برای نمونه از وبسایت OMDB ،Rotten Tomatoes و IMDB هستید. اما زمانی که کارها را روی گیتهاب میبرید در زمان آپلود کردن مجموعه داده IMDB با خطایی مانند زیر مواجه میشوید:
در این زمان است که متوجه میشوید گیت و گیتهاب محدودیت اندازه فایل 100 مگابایت دارند. فایلهایی با اندازههای بزرگتر از 50 مگابایت پیام هشدار دریافت میکنند، اما میتوان آنها را push کرد.
نخستین راهکاری که در این حالت به صورت طبیعی به ذهن میرسد این است که کار را با ارسال تک به تک فایلها ادامه دهد. اما اگر این راهکار به هر دلیلی ممکن نباشد، باید گزینه بعدی یعنی ذخیرهسازی به روش Large File Storage را در گیت بررسی کنیم. برای این که Git LFS را درک کنیم باید ابتدا گیت را بشناسیم. بنابراین قبل از بررسی LFS اندکی در مورد گیت توضیح میدهیم.
گیت چیست؟
گیت یک سیستم کنترل نسخه توزیع یافته است، یعنی کل سابقه ریپازیتوری در طی فرایند کلون کردن به کلاینت انتقال مییابد.
اگر بخواهیم این موضوع را کمی بیشتر باز کنیم، باید ابتدا سیستم کنترل نسخه را توضیح دهیم. «سیستم کنترل نسخه» (Version Control System) ابزاری است که به مدیریت تغییرها در کد منبع، فایلها و دیگر اَشکال اطلاعات میپردازد. بدین ترتیب تغییرها به صورت commit ردگیری میشوند. Commit در واقع تصاویری از ویرایشها در نقاط زمانی مشخص هستند. در سوی دیگر یک سیستم کنترل نسخه توزیع یافته نوعی از سیستم کنترل نسخه است که امکان انتقال همه کدبیس شامل همه سوابق (و همه تغییرها) به رایانه هر توسعهدهنده را فراهم میسازد. بدین ترتیب هر توسعهدهنده میتواند روی پروژهای کار کند و همزمان کل تایملاین ویرایشهای انجام یافته روی پروژه را ببیند.
تاریخچه گیت
گیت نخستین بار در سال 2005 از سوی «لینوس تروالدز» (Linus Torvalds) و در نتیجه توقف استفاده از سیستم کنترل نسخه Bitkeeper خلق شد. دلیل توقف لینوس و همکارانش نیز این بود که Bitkeeper دیگر رایگان نبود و پولی شده بود. بر اساس گزارشها لینوس پس از تلاش برای یافتن یک سیستم کنترل نسخه رایگان جایگزین برای Bitkeeper تصمیم گرفت تا سیستم کنترل نسخه خود را بسازد که کوچک و سریع (کمتر از سه ثانیه زمان بگیرد) باشد و از انشعاب پشتیبانی کند. همچنین این سیستم باید کاملاً مخالف سیستمهای کنترل نسخه همزمان و شامل safeguards برای صحت دادهها میبود.
از آنجا که گیت ساخته شده است تا کوچک و سریع باشد، در ابتدا صرفاً برای پشتیبانی از سورس کد ساخته شد و از فایلهای بزرگ پشتیبانی نمیکرد. توجه کنید که گیت یک سیستم کنترل نسخه است یعنی هر بار که پروژهای کلون یا pull میشود همه سابقه کامل تغییرهای یک پروژه انتقال مییابد. زمانی که یک کامیت اضافه میشود، به سوابق افزوده میشود و موجب افزایش اندازه فایل کلی پروژه میشود و در طی زمان این مقدار بسیار افزایش مییابد.
با این وجود، رشتههای زیادی وجود دارند که در آن پروژههایی با فایلهای بزرگ ایجاد میشوند و این حالت شامل حوزه فایلهای موسیقی، تصویر و مجموعههای دادههای علمی نیز میشود. بنابراین اینک سؤال این است که در چنین موقعیتهایی چه باید کرد؟ این همان نقطهای است که Git LFS به کارمی آید.
«ذخیرهسازی فایل بزرگ» Git یا LFS به چه معنا است؟
Git LFS یک اکستنشن گیت است که در Go برنامهنویسی شده و از سوی توسعهدهندگانی در Atlassian و Github و همچنین مشارکتکنندگان اوپنسورس جهت دور زدن محدودیت اندازه فایل در گیت ساخته شده است. این کار از طریق ذخیرهسازی فایلهای بزرگ در یک مکان مجزا از ریپازیتوری و قرار دادن اشارهگرهای فایل در ریپازیتوری که مستقیماً به محل فایل اشاره میکنند صورت میپذیرد.
بهترین روش برای درک طرز کار LFS این است که ابتدا برای لحظهای همه چیز را در مورد Github ،Bitbucket ،Gitlab و همه ریپازیتوریهای ریموت فراموش کنیم. در این مرحله صرفاً روی رایانه محلی تمرکز میکنیم که در تصویر زیر با شکل یک نمایشگر با سه بخش Working Copy ،Local Repository و LFS Cache نمایش یافته است.
ریپازیتوری محلی
«ریپازیتوری محلی» (local repository) آن دایرکتوری یا پوشهای است که روی رایانه خود میبینید و با استفاده از دستور git init به عنوان ریپازیتوری گیت مقداردهی شده و یا از ریپازیتوری ریموت کلون شده است. «کپیِ کاری» (Working Copy) یک بازنمایی از فایلها و پوشههایی است که در ریپازیتوری محلی ویرایش میشوند. LFS Cache مکان ذخیرهسازی مجزایی است که در ریپازیتوری محلی ویرایش میشود. LFS Cache فضای ذخیرهسازی مجزایی برای فایلهای بزرگ است که از طریق گیت push میشوند. این اصطلاحها را به ذهن خود بسپارید، چون در زمان توضیح طرز کار Git LFS در بخش بعدی به کار خواهند آمد.
کار با Git LFS
نکته مهم در مورد Git LFS این است که میتوان در آن همچنان از دستورهای عادی و گردش کار معمولی گیت که کاملاً شناخته شده هستند استفاده کرد. تنها تغییر در این مورد برخی دستورهای اضافی و مکان ذخیرهسازی مجزایی هستند که باید در خاطر داشت.
اکنون که اطلاعاتی در مورد گیت و Git LFS داریم، در ادامه به بررسی روش استفاده از آن میپردازیم. دو سناریو در این خصوص وجود دارد، اما ابتدا باید Git LFS را از طریق Homebrew با دستور زیر دانلود کنیم:
brew install git-lfs
در مورد سیستمهای غیر مَک نیز امکان دانلود از طریق وبسایت (+) وجود دارد.
سناریوی اول
در این سناریو از Git LFS پس از دریافت پیام خطایی در زمان استفاده از دستورهای معمولی گیت استفاده میکنیم.
در این مثال یک ریپازیتوری جدید داریم که یک فایل داده بزرگ (1.9 گیگابایت) در آن قرار دادهایم. ما میخواهیم مطمئن شویم که هر تغییری در مورد فایلهای داده ردگیری میشود و در نهایت به صورت ریموت پشتیبانگیری خواهد شد. ابتدا از دستورهای معمولی گیت برای stage کردن فایل (git add) استفاده میکنیم، یک کپی از تغییرها را در ریپازیتوری محلی (git commit) ذخیره میکنیم و کپی را به ریپازیتوری ریموت ارسال میکنیم (git push). خروجی این دستورها به صورت زیر است:

این خطا را چگونه میتوان حل کرد؟ یک راهحل این است که تغییرها را با استفاده از git reset بازگردانی کنیم و یا از ذخیره فایل صرفنظر کنیم و آن را به صورت zip و با اندازه کوچکتر دربیاوریم و یا این که مسیر خود را با Git LFS ادامه دهیم. گزینه دیگر این است که از همان جایی که کار متوقف شده اقدام به یکپارچهسازی Git LFS بکنیم و بدین ترتیب امکان ادامه فرایند وجود خواهد داشت. ما در این بخش این مسیر را دنبال میکنیم.
گام 1
نخستین گام در این مسیر آن است که Git LFS را نصب کرده و از طریق اجرای دستور زیر، ریپازیتوری خاصی را برای آن فعالسازی کنیم:
git lfs install
با این که قبلاً Git LFS را روی سیستم خود نصب کردهایم، اما باید به آن اعلام کنیم که کدام ریپازیتوری ها به خدماتش نیاز دارند. برای قیاس یک شرکت ارائهدهنده سرویس ذخیرهسازی را در نظر بگیرید. چنین شرکتهایی در دسترس ما هستند تا آیتمهایی را در آنها ذخیره کنیم، اما به صورت خودکار به سراغ ما نمیآیند تا فایلهایمان را ذخیرهسازی کنند. بلکه ما باید ابتدا با عقد قرارداد یک رابطه با این شرکت برقرار کنیم. همین حالت در اینجا نیز صدق میکند. برای فعالسازی سرویسهای Git LFS در یک ریپازیتوری خاص یا اعلام این که سرویسهای Git LFS برای کدام ریپازیتوری باید فعال شود از دستور زیر استفاده میکنیم:
git lfs install
گام 2
با دستور زیر به Git LFS اعلام کنید که کدام فایلها باید ردگیری شوند:
git lfs track “*.file_extension”
در این مورد نیز باید به Git LFS اعلام کنیم که کدام فایلها و یا کدام انواع فایلها را میخواهیم ردگیری کند، بدین ترتیب فایلها میتوانند در مکان دیگری به جز ساختار گیت خیره شوند تا از دریافت پیام خطای قبلی جلوگیری شود. به این منظور دستور فوق را اجرا کنید.
برای مثال اگر لازم است همه فایلهای CSV ردگیری شوند دستور زیر را اجرا کنید:
git lfs track “*.csv”
یا اگر لازم است همه فایلهای jpeg ردگیری شوند، دستور زیر را وارد کنید:
git lfs track “*.jpg”
کاراکتر ستاره (*) نشاندهنده همه فایلها است. استفاده از گیومه نیز برای اجرای این کد ضروری است. بدون وجود گیومه با خطای زیر مواجه میشویم:
همان طور که وقتی از یک شرکت ذخیرهسازی میخواهیم شروع به ذخیرهسازی آیتم بکند، یک صورتحساب برای ما ارسال میکند، در این مورد نیز وقتی یک فایل را با Git LFS ردگیری کنیم، یک فایل gitattributes. ایجاد خواهد شد. اگر فایل gitattributes. از قبل موجود باشد، این فایل به صورت یک خط جدید در آن اضافه میشود.
گام 3
در این بخش با دستورهای Git add ،commit و push فایل gitattributes. را در ریپازیتوری خود قرار میدهیم.
Git LFS نیز همانند فایل gitattributes.، فایلهای جدید را ردگیری میکند، و تغییرهای صورت گرفته به صورت خودکار در فایل gitattributes. بهروزرسانی میشوند. برای این که مطمئن شویم تغییرها ردگیری میشوند، هر بار که فایل gitattributes. بهروزرسانی میشود، باید stage و commit شود چون در غیر این صورت ممکن است در ادامه با خطایی مواجه شویم.
گام 4
اینک میخواهیم با رمز اصلی این سناریو که استفاده از git LFS برای انتقال کامیتها از گیت به Git LFS است آشنا شویم.
آنچه موجب میشود بتوانیم در حالت کنونی و بدون نیاز به undo کردن کامیتها و راهاندازی مجدد فرایند از Git LFS استفاده کنیم، یک خط کد جالب است که امکان انتقال یا «migrate» کامیتها از گیت به Git LFS را فراهم میسازد. برای این که بتوانیم کامیتها را انتقال دهیم باید دستور زیر را اجرا کنیم:
git lfs migrate import — include “*.file_extension”
برای دیدن انواع فایلی که در کامیتها هستند و میتوانند از سوی Git LFS ردگیری شوند، میتوانیم دستور زیر را اجرا کنیم:
git lfs migrate info
با انتقال دادن کامیتها، میتوانیم به مرحله بعدی برویم و تغییرها را به گیتهاب push کنیم. در این خصوص در بخش بعدی بیشتر توضیح میدهیم:
نکته مهم: انتقال کامیتها شامل بازنویسی سابقه هستند. میتوان یک تگ اضافه کرد تا از بازنویسی تغییرهای لیست شده در سابقه جلوگیری کرد، اما این کار از اجرا شدن آن خط کد جلوگیری خواهد کرد.
گام 5
در نهایت دستور git push را اجرا میکنیم تا تغییرها را به گیتهاب پوش کنیم و کامیت بزرگ (یعنی فایلهای بزرگ) نیز به Gif LFS کامیت شوند.
پس از انتقال کامیتها به Git LFS در حال حاضر یک ریپازیتوری محلی گیت داریم که با یک تغییر بهروزرسانی شده است. در این مورد یک فایل داده جدید اضافه شده است که به وسیله اشارهگر فایل به Git LFS اشاره دارد. همچنین یک کش Git LFS محلی وجود دارد که اینک به ذخیره سای فایل داده میپردازد. در مرحله بعدی تغییرها را به گیتهاب پوش میکنیم. ریپازیتوری گیت محلی که دارای فایلهایی در چارچوب محدودیت اندازه تعیین شده باشند (یعنی فایلهای کد منبع و فایل اشارهگر) در گیتهاب ذخیره میشوند که میزبان گیت مشخص شده در تصویر زیر است و کش Git LFS در فضای ذخیرهسازی Git LFS روی کلود ذخیره میشود.
سناریوی دوم: استفاده از Git LFS از ابتدا
اگر بدانیم که فایلهای بزرگی در ریپازیتوری وجود دارند، میتوانیم از Git LFS از همان ابتدا استفاده کنیم و مراحل 1 تا 3 بررسی شده فوق را طی کنیم. پس از طی این مراحل به دستورهای معمولی گیت به صورت git add ،git commit بازمیگردیم تا تغییرها را در ریپوی محلی stage و ذخیره کنیم. سپس گام 5 فوق را اجرا میکنیم تا تغییرها را به گیتهاب و دیگر میزبانهای گیت و فضای ذخیره ریموت Git LFS پوش کنیم.
سخن پایانی
چنانکه مشاهده کردید روش Git LFS برای دور زدن مشکل ذخیرهسازی فایلهای بزرگ در سیستم کنترل نسخه گیت کاملاً سرراست است. کافی است پنج گام فوق را به خاطر بسپارید تا این فرایند را طی کنید. pull کردن تغییرها از یک ریپاریتوزی ریموت نیز کاملاً سر راست است. در این حالت همان دستورهای گیت که معمولاً استفاده میکنیم، یعنی git pull یا git fetch و git merge مورد نیاز هستند.
با استفاده از git pull میتوان تغییرها را که شامل فایل داده ذخیره شده در Git LFS میشود، روی سیستم محلی بارگذاری کرد. زمانی که تغییرها را از ریپازیتوری ریموت pull میکنیم، تغییرهای ریپازیتوری ریموت و هر شیء دیگری که در Git LFS ذخیره شده باشد، نیز روی رایانه محلی pull میشوند.
شاید همه موارد فوق در مواجهه نخست کمی سردرگمکننده به نظر برسند، بنابراین در ادامه نکاتی را که میتوان در این مقاله جمعبندی کرد، ارائه کردهایم.
- افرادی که به نظرشان گیت پیچیده میآید، باید بدانند که این مطلب بر پیچیدگی موضوع میافزاید. این مهمترین چالش این افراد در زمان یادگیری Git LFS خواهد بود. یادگیری دقیق دستورهای گیت، گردش کار گیت و شیوه تطبیق آن با Git LFS کلید یادگیری گامهای طرحشده در این آموزش است.
- حتی در زمان استفاده از Git LFS نیز محدودیت اندازه فایل 2 گیگابایت وجود دارد که از سوی گیتهاب تعیین شده است. هر چیزی بزرگتر از این، باید روی فضای ذخیرهسازی ابری دیگری قرار گیرد.
- Git LFS یک پروژه فعال اپنسورس است که به صورت مداوم بهبود مییابد. در گیتهاب این پروژه لیستی از issue-های جاری وجود دارد (+) که در حال حل هستند.
- همچنین برخی issue-ها وجود دارند که در زمان تلاش برای ادغام تداخلها بروز مییابند. بنابراین بهتر است پیش از push کردن تغییرها و ادغام آنها یک مشورت درون تیمی وجود داشته باشد.
- توجه داشته باشید که فایلهای بزرگتر در زمان push شدن به ریپازیتوری ریموت ممکن است کمی کند باشند.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی
- آموزش گیت (Git) برای مدیریت نسخه توزیع شده
- مجموعه آموزشهای دروس علوم و مهندسی کامپیوتر
- راهنمای پیشرفته Git برای مبتدیان — به زبان ساده
- 1۰ دستور گیت (Git) که باید آنها را بدانید — فهرست کاربردی
==
سلام. خیلی خیلی ممنون به خاطر مطالب مفیدتون. ببخشید من یه چیزی را متوجه نشدم. محدودیت 2 گیگابایت برای هر فایله یا برای کل ریپوزیتوری؟ منظورم اینه که مثلا ما داخل ریپوزیتوری میتونیم 5 تا فایل 1 گیگی آپلود کنیم؟ سوال دیگه اینکه به جز git lfs ریپوزیتوری دیگه ای سراغ ندارین که بشه فایل های حجیم را داخلش آپلود کرد؟ خیلی ممنون
سلام
آیا امکان ردیابی یک فایل خاص از طریق نوشتن آدرس نسبی آن داخل گیومه با git lfs وجود دارد؟
git lfs install
git lfs track “Powerpoint/UAVSAR_Slideshow.pps”
git add .gitattributes
https://stackoverflow.com/q/57140250/1245120
سلام
بله امکان این کار وجود دارد. توجه داشته باشید که دستورهای gif lfs همواره نسبت به آن دایرکتوری که از آنجا آغاز میشوند تعریف خواهند شد.
ممنون از توجه شما.