Налаштування Git LFS: зберігання великих файлів і прискорення CI/CD

Репозиторій зростає, збірки гальмують, а вивантаження займає години? Ми налаштовуємо Git LFS під ключ: виносимо великі файли з репозиторію, прискорюємо збірки й передаємо команді зрозумілі регламенти роботи. Час очікування збірки скорочується в рази, а історія проєкту залишається цілою.
Часті запитання

Чому Git LFS потрібен: репозиторій зростає, збірки сповільнюються

Git зберігає кожну версію файлу окремим об’єктом, тому історія комітів зростає разом із кількістю правок. Поки в репозиторії лише вихідний код, це майже непомітно — дельта-стиснення з’їдає різницю між сусідніми версіями.

Щойно туди потрапляють бінарні артефакти — медіа, макети, моделі, тестові бази, зібрані дистрибутиви — кожна правка додає в історію повноцінну нову копію файлу, а не різницю.

Далі вмикається каскад. Клонування репозиторію розтягується на десятки хвилин, бо клієнт викачує всі версії файлу, включно з давно непотрібними.

Агент збірки витрачає більше часу на розігрів робочої копії, ніж на саму збірку, паралельні завдання впираються в диск і мережу, а кеш постійно скидається при переповненні. Чим активніша команда, тим сильніше роздувається історія — і тим дорожчий кожен наступний прогін.

Паралельно впирається публікація: хостинг відмовляється приймати зміни, коли розмір надісланих об’єктів перевищує ліміт, а вивантаження артефактів падає через перевищення часу очікування.

Лікувати це переписуванням історії заднім числом ризиковано — ламаються гілки, посилання на коміти й підписи, а всім розробникам доводиться заново клонувати проєкт. Водночас великі файли в репозиторії залишаються звичною практикою, бо «так історично склалося».

Git LFS змінює саму модель зберігання: великі об’єкти вирушають в окреме сховище, а в репозиторії залишаються вказівники — вони важать байти й не зростають від версії до версії.

Розбираємо, як це закривається на практиці: від вибору місця зберігання й міграції вже накопиченої історії до правил, які не дають новим бінарним артефактам просочуватися повз LFS.

Що змінюється після винесення великих файлів із репозиторію

Великі файли — бінарні збірки, медіа, макети, ваги моделей — тримають історію репозиторію в заручниках: кожна правка додає нову повну копію об’єкта, а попередні залишаються в історії назавжди.

У Git LFS вміст замінюється вказівником, а самі дані вирушають в окреме об’єктне сховище. Репозиторій знову зберігає текстові зміни, а не артефакти.

Перший вимірюваний ефект — час клонування. Розробник і машина збірки витягують лише актуальні версії великих файлів, а не всю їхню історію.

Робоча копія перестає роздуватися: замість гігабайтів бінарників — кілобайти вказівників, перемикання між гілками вкладається в секунди навіть на вузькому каналі.

Другий — прискорення збірки. Кроки, які раніше чекали вивантаження артефактів з історії, отримують їх на запит, а проміжний кеш не перебудовується повністю на кожному коміті.

Водночас зникає цілий клас відмов: переповнення ліміту сховища, обрив під час завантаження великого об’єкта, падіння завдання через брак місця.

Стабільність збірки тут — не про швидкість, а про передбачуваність: завдання падає на помилці в коді, а не на інфраструктурі. Плата за це — дисципліна середовища: клієнт LFS в образі машини збірки, правила зберігання й резервні копії об’єктного сховища. Історія при цьому зберігається повністю — відкат на будь-який минулий реліз залишається можливим.

Варіанти зберігання великих файлів: порівняння підходів

Вибір способу зберігання великих файлів визначає, як швидко клонується репозиторій, скільки займає історія і що станеться, якщо зовнішня служба виявиться недоступною. Нижче — чотири варіанти, між якими реально обирають на проєктах.

Варіант Коли підходить Обмеження
Звичайне зберігання в репозиторії Невеликі бінарники, які потрібні всій команді й рідко змінюються Кожна версія залишається в історії назавжди: клон зростає разом із кількістю правок, а не з розміром файлу
Виділене сховище вказівників Важкі файли у звичному потоці роботи: графіка, медіа, тестові набори даних Потрібен налаштований сервер і правило очищення; без нього обсяг сховища зростає безконтрольно
Зовнішнє файлове сховище Великі обсяги, розмежування доступу, віддача даних мережею Репозиторій і збірка залежать від чужої доступності та мережевого каналу
Локальне зберігання Чорнові матеріали, яким не місце в загальному доступі Немає відтворюваності: інший інженер або агент збірки не отримає ті самі дані

На практиці найчастіше працює комбінація: Git LFS закриває те, що потрібно всім у потоці збірки, зовнішнє сховище — великі медіа й артефакти, локальне — чернетки.

Ми дивимося, які файли беруть участь у збірці, які змінюються часто, а які потрібні лише тимчасово, і на цій основі розкладаємо їх по сховищах.

Як відбувається впровадження: від аудиту до передачі регламентів

Впровадження Git LFS — це не встановлення розширення, а зміна схеми зберігання всіх важких артефактів репозиторію. Порядок робіт вибудувано так, щоб на момент перемикання жодна ревізія не загубилася і команди не простоювали. Нижче — як влаштований процес від аудиту до передачі регламентів.

  1. Аудит репозиторію. Рахуємо обсяг та історію: які розширення дають основну вагу, скільки ревізій зачеплено, хто і як часто комітить великі файли. На виході — перелік шляхів, які переводимо на зовнішнє сховище, та оцінка розміру після міграції.
  2. План міграції. Визначаємо, чи переписуємо історію повністю, чи переводимо лише нові коміти, узгоджуємо вікно, коли правки в основну гілку призупинено. Фіксуємо порядок відкату, якщо перевірка не пройде.
  3. Налаштування сховища. Розгортаємо або підключаємо об’єктне сховище, задаємо правила зберігання: термін життя старих версій, ліміти на розмір об’єкта, розмежування доступу за ролями. Прописуємо фільтри й правила в конфігурації репозиторію.
  4. Переведення команд і збірки. Оновлюємо налаштування в розробників і на агентах збірки, щоб важкі файли завантажувалися на вимогу, а не в кожному клоні. Для репозиторію на десятки гігабайт це скорочує час отримання робочої копії в рази.
  5. Перевірка цілісності. Звіряємо контрольні суми об’єктів до і після міграції, збираємо проєкт з нуля на чистому клоні, перевіряємо доступність старих ревізій і тегів. Тільки після цього закриваємо вікно міграції.
  6. Передача в експлуатацію. Віддаємо регламенти й інструкції, налаштовуємо оповіщення про зростання сховища, проводимо навчання команди й фіксуємо відповідального за правила.

Правила вказівників, доступи та документація проєкту

Впровадження вважається завершеним не тоді, коли великі файли перестали гальмувати клонування, а коли в команди є набір артефактів, що дозволяє змінювати правила без нас. Нижче — те, що замовник отримує на виході і що ми розбираємо з його інженерами на передачі.

  • Файл правил зіставлення — які розширення та шляхи йдуть у LFS, а які залишаються у звичайному індексі. Нова категорія бінарних файлів додається правкою одного рядка, а не перезбиранням репозиторію.
  • Конфігурація вказівників і сховища — адреса об’єктного сховища, режим блокування «незливаних» файлів, обмеження на паралельні передачі. Ті самі налаштування на робочих машинах і на агентах збірки, щоб поведінка не розходилася.
  • Схема зберігання — де фізично лежать об’єкти, як влаштований кеш на агентах, які правила очищення діють: скільки ревізій тримаємо, що видаляється першим, як відновлюється об’єкт після помилкового видалення.
  • Політики доступу — які облікові записи й токени можуть читати та записувати об’єкти, як видаються права підрядникам і зовнішнім командам, де зберігаються секрети збірки і як вони ротуються.
  • Інструкції для команди — як правильно клонувати репозиторій із великими файлами, що робити при обриві передачі, як звільнити місце в робочій копії, як поставити блокування на файл, який не можна зливати автоматично.
  • Регламент роботи — порядок правки файлу правил: хто погоджує переведення нової категорії файлів у LFS, як перевіряється, що вказівник не залишився без свого об’єкта, хто відповідає за зростання сховища.
  • Перевірки у збірці — автоматичний контроль «вказівник без об’єкта» і ліміту розміру, щоб проблема виявлялася на етапі збірки, а не при клонуванні в нового розробника.

Цього набору достатньо, щоб правила змінювала ваша команда: розширювала список відстежуваних файлів, підключала нових людей і зовнішні репозиторії, не повертаючись до нас за кожним налаштуванням. Опишіть вашу задачу — повернемося з оцінкою та планом передачі.

Кейс: як розвантажили репозиторій і прискорили збірку

Репозиторій продукту зростав не за рахунок коду: поруч із вихідниками лежали макети інтерфейсу, тестові відеозаписи та набори даних для перевірки вивантажень.

Клонування на чистій машині займало близько 40 хвилин, робоча копія була в чотирнадцять разів важча за сам код, а з 30 хвилин збірки 12 йшли на викачування історії.

Вивантаження падали приблизно в кожній п’ятій спробі — зазвичай через перевищення часу очікування під час отримання вкладень.

Розділили потоки: код залишився в основній історії, важкі файли перевели на Git LFS з правилами в .gitattributes за масками типів, а тестові набори, що рідко змінюються, винесли в окреме сховище з версіонуванням за посиланням.

В образ збірника додали попереднє завантаження потрібних об’єктів, щоб кроки не витягували їх по одному через мережу, обмежили права запису і включили перевірку на файли понад поріг — коміт більше не може непомітно обтяжити історію.

Після перенесення клонування вклалося в 4 хвилини, збірка скоротилася до 11, робоча копія в розробника стала меншою в чотирнадцять разів. Падінь на вивантаженні за квартал — одиниці замість кожного п’ятого запуску, частка неуспішних доставок упала нижче одного відсотка.

Репозиторій тепер зростає передбачувано: політика зберігання обмежує розмір службового сховища, а відкат на попередню версію асетів залишається доступним.

Чим Git LFS відрізняється від звичайного зберігання в репозиторії

При звичайному зберіганні бінарний артефакт — образ, датасет, відео — комітиться в ту саму базу об’єктів, що й код. Дельта-стиснення, яке тримає історію текстових файлів компактною, на бінарниках не працює: кожна версія лягає повною копією.

Видалення з поточної гілки нічого не звільняє — об’єкт залишається в історії, і клон витягує всі його ревізії.

Git LFS змінює схему: в репозиторій потрапляє текстовий вказівник — тип об’єкта, хеш і розмір, — а самі байти вирушають в окреме сховище. Історія комітів, гілки й теги залишаються на місці, але дерево версій важить стільки, скільки займають рядки вказівників.

Різниця підходів проявляється не в командах розробника, а в тому, що саме витягується мережею при клоні та збірці.

Відновлення робочого дерева теж відрізняється. Звичайний клон викачує всю історію великих файлів, включно з версіями, видаленими багато релізів тому; режим вказівників віддає лише потрібні поточному дереву об’єкти.

Плата — мережева залежність: без доступу до сховища на місці файлів залишаться текстові заглушки, а фільтри потрібно налаштувати до першого клону.

При розгалуженні однакові файли дедуплікуються за хешем: одна копія в релізній і робочій гілці зберігається один раз, тоді як у звичайній схемі об’єкт живе в усіх гілках і сповільнює обхід історії.

Обмеження зберігання при цьому не зникають, а переїжджають: з’являється окремий сервер, квоти за обсягом і трафіком, своя політика життєвого циклу та бекап, не пов’язаний із репозиторієм.

У конвеєрі збірки це дає вибіркове завантаження потрібних шляхів замість повної історії — підготовка середовища прискорюється, але крок завантаження об’єктів налаштовується явно, інакше збірка мовчки отримає вказівники замість файлів.

Сумніви щодо зберігання, доступів і відновлення файлів

Впровадження LFS рідко закінчується однією командою відстеження. В історії вже лежать бінарні об’єкти звичайними файлами, тому потрібен план перенесення: без нього свіжий клон витягує старі гілки повністю.

Друга група сумнівів — експлуатація: де фізично лежать об’єкти і хто до них має доступ. Окремо перевіряємо доступність сховища в момент збірки: агент збірки або зупиняється з явною помилкою, або бере об’єкти з локального кешу — це задається заздалегідь, а не в момент збою.

Що буде зі старими гілками та історією?

Старі гілки переводимо окремим проходом: об’єкти виносяться з історії, на їхнє місце стають вказівники з .gitattributes. Непідтримувані гілки зазвичай закриваємо й залишаємо архівом — переписувати їх дорожче, ніж користь.

Як надати доступ зовнішнім підрядникам?

Підряднику видаємо окремий обліковий запис: лише читання і лише потрібний простір об’єктів. Він забирає великі файли, але не може перезаписати чужі, а доступ відкликається після здачі робіт.

Як відновлювати великі файли з резервної копії?

Копія репозиторію марна — у ній вказівники, а не самі дані. У регламент додаємо бекап сховища об’єктів, а відновлення перевіряємо на тестовому клоні, щоб неповну копію не виявити в момент аварії.

Обговоримо задачу: схема зберігання та порядок міграції

На обговорення замовник приносить список репозиторіїв і розуміння, які файли туди потрапляють: бінарні збірки, моделі, медіа, вивантаження із зовнішніх систем.

Корисні поточні правила трекінгу, розмір робочої копії в розробників і скарги на час клонування чи збірки — за ними одразу видно, де вузьке місце і що саме прискорюємо.

З цього збирається план робіт: схема зберігання (де розміщується LFS-сховище, які маски файлів ідуть у трекінг, які ліміти ставимо), порядок впровадження за репозиторіями та оцінка строків.

Масовою міграцією не починаємо — спочатку пілот на одному репозиторії, щоб перевірити клон, збірку та відкат на живому конвеєрі.

  • інвентаризація репозиторіїв і файлів, які переводяться в LFS;
  • схема зберігання: розміщення сховища, правила трекінгу за масками, ліміти на розмір;
  • порядок впровадження: пілотний репозиторій, потім решта хвилями;
  • міграція історії та очищення вже закомічених великих об’єктів;
  • правки конвеєра збірки, кешу залежностей і правил доступу для агентів;
  • ролі та права: хто читає і пише у сховище, як видаються ключі;
  • план відкату, якщо клон або збірка деградують після переходу.

Повертаємося з оцінкою строків і обсягу робіт: етапи, що робимо ми, що потрібно з боку замовника, критерії приймання — час клонування, розмір робочої копії, тривалість збірки. Опишіть задачу — повернемося з оцінкою та планом.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1393
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1368
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    815
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1139