Щоб пояснити, що таке керування версіями, я буду використовувати аналогії. Якщо потрібно більш точне пояснення, зверніться до статті вікіпедії.
Я грав в комп’ютерні ігри майже все своє життя. А ось використовувати системи керування версіями почав вже будучи дорослим. Вважаю, я такий не один, і порівняння цих двох занять може допомогти поясненню і розумінню концепції.
Уявіть, що редагування коду або документа – гра. Просунувшись далеко, ви захочете зберегтися. Для цього ви натиснете на кнопку „Зберегти“ у вашому улюбленому редакторі.
Але це перезапише стару версію. Це як в стародавніх іграх, де був тільки один слот для збереження: звичайно, ви можете зберегтися, але ви більше ніколи не зможете повернутися до попереднього стану. Це прикро, оскільки попереднє збереження могло вказувати на одне з дуже цікавих місць у грі і, можливо, одного разу ви захочете повернутися до нього. Або, що ще гірше, ви зараз перебуваєте у безвиграшному становищі і змушені починати заново.
Під час редагування ви можете „Зберегти як …“ в інший файл або скопіювати файл куди-небудь перед збереженням, щоб уберегти більш старі версії. Можливо, заархівувавши їх для економії місця на диску. Це найпримітивніший вид керування версіями, до того ж він вимагає інтенсивної ручної роботи. Комп'ютерні ігри пройшли цей етап давно, у більшості з них є безліч слотів для збереження з автоматичними тимчасовими мітками.
Давайте трохи ускладнимо умови. Нехай у вас є кілька файлів, використовуваних разом, наприклад, вихідний код проекту або файли для вебсайту. Тепер, щоб зберегти стару версію, ви повинні скопіювати весь каталог. Підтримка безлічі таких версій вручну незручна і швидко стає дорогим задоволенням.
У деяких іграх збереження – це і є каталог з купою файлів всередині. Ігри приховують деталі від гравця і надають зручний інтерфейс для керування різними версіями цього каталогу.
У системах керування версіями все точно так само. У всіх них є приємний інтерфейс для керування каталогом з вашим скарбом. Можете зберігати стан каталога так часто, як забажаєте, а потім відновити будь-яку з попередніх збережених версій. Але, на відміну від комп'ютерних ігор, вони істотно економлять дисковий простір. Зазвичай від версії до версії змінюється тільки кілька файлів і то ненабагато. Зберігання лише відмінностей замість повних копій потребує менше місця.
А тепер уявіть дуже складну комп’ютерну гру. Її настільки складно пройти, що безліч досвідчених гравців по всьому світу вирішили об'єднатися і використовувати загальні збереження, щоб спробувати виграти. Проходження на швидкість — живий приклад. Гравці, що спеціалізуються на різних рівнях гри, об’єднуються, щоб в результаті отримати приголомшливий результат.
Як би ви організували таку систему, щоб гравці змогли легко отримувати збереження інших? А завантажувати свої?
У минулі часи кожен проект використовував централізоване керування версіями. Який-небудь сервер зберігав всі збережені ігри. І ніхто більше. Кожен тримав лише кілька збережень на своїй машині. Коли гравець хотів пройти трохи далі, він завантажував останнє збереження з головного сервера, грав небагато, зберігався і вивантажував вже своє збереження назад на сервер, щоб інші могли ним скористатися.
А що якщо гравець з якоїсь причини захотів використовувати більш стару збережену гру? Можливо, нинішнє збереження безвиграшне, бо хтось забув взяти якийсь ігровий предмет ще на третьому рівні, і потрібно знайти останнє збереження, де гру все ще можна закінчити. Або, можливо, хочеться порівняти дві більш старі збережені гри, щоб встановити внесок конкретного гравця.
Може бути багато причин повернутися до більш старої версії, але вихід один: потрібно запросити ту стару збережену гру у центрального сервера. Чим більше збережених ігор потрібно, тим більше знадобиться зв’язуватися з сервером.
Системи керування версіями нового покоління, до яких відноситься Git, відомі як розподілені системи, їх можна розуміти як узагальнення централізованих систем. Коли гравці завантажуються з головного сервера, вони отримують кожну збережену гру, а не тільки останню. Вони як би дзеркалюють центральний сервер.
Ці початкові операції клонування можуть бути ресурсоємними, особливо при довгій історії, але сповна окупаються при тривалій роботі. Найбільш очевидна пряма вигода полягає в тому, що якщо вам навіщось потрібна більш стара версія, взаємодія з сервером не знадобиться.
Широко поширена помилка полягає в тому, що розподілені системи непридатні для проектів, які потребують офіційного централізованого сховища. Ніщо не може бути більш далеким від істини. Отримання фотознімку не призводить до того, що ми крадемо чиюсь душу. Точно так само клонування головного сховища не зменшує його важливість.
У першому наближенні можна сказати, що все, що робить централізована система керування версіями, добре сконструйована розподілена система може зробити краще. Мережеві ресурси просто дорожчі локальних. Хоча далі ми побачимо, що в розподіленому підході є свої недоліки, ви навряд чи помилитеся у виборі, керуючись цим наближеним правилом.
Невеликому проектом може знадобитися лише частинка функціоналу, пропонованого такою системою. Але використання погано масштабованої системи для маленьких проектів подібно використанню римських цифр в розрахунках з невеликими числами.
Крім того, проект може вирости понад початкові очікування. Використовувати Git з самого початку — це як тримати напоготові швейцарський ніж, навіть якщо ви всього лише відкриваєте ним пляшки. Одного разу вам шалено знадобиться викрутка і ви будете раді, що під рукою є щось більше, ніж проста відкривачка.
Для цієї теми аналогія з комп'ютерною грою стає занадто натягнутою. Замість цього, давайте повернемося до редагування документа.
Отже, припустимо, що Марічка вставила рядок на початку файлу, а Іван — в кінці. Обоє вони закачують свої зміни. Більшість систем автоматично зробить розумний висновок: прийняти і об'єднати їх зміни так, щоб обидві правки — і Марічки, і Івана — були застосовані.
Тепер припустимо, що і Марічка, і Іван внесли різні зміни в один і той же рядок. У цьому випадку неможливо продовжити без втручання людини. Той із них, хто другим закачає на сервер зміни, буде поінформований про конфлікте злиття (merge conflict), і повинен або віддати перевагу одній змінні перед іншою, або скорегувати увесь рядок.
Можуть траплятися і більш складні ситуації. Системи керування версіями вирішують прості ситуації самі і залишають складні для людини. Зазвичай таку їхню поведінку можна налаштовувати.