Перейти до вмісту

Модуль 0.6: Основи Git — Відстежуйте свою роботу

Модуль 0.6: Основи Git — Відстежуйте свою роботу

Розділ «Модуль 0.6: Основи Git — Відстежуйте свою роботу»

Складність: [ПОЧАТКІВЕЦЬ] Час на проходження: 45 хвилин Передумови: Модуль 0.5 (Редагування файлів)

Що ви зможете зробити

Розділ «Що ви зможете зробити»

Після завершення цього модуля ви зможете:

  • Ініціалізувати локальні репозиторії Git та налаштувати ідентифікацію користувача для точного атрибутування комітів.
  • Побудувати логічну історію комітів шляхом вибіркового додавання змін у файлах до індексу за допомогою git add та git commit.
  • Діагностувати неочікувані стани репозиторію шляхом аналізу результатів виконання git status, git log та git diff.
  • Синхронізувати локальні репозиторії з віддаленими серверами за допомогою git push та git pull.
  • Створити файл .gitignore, щоб запобігти відстеженню конфіденційних даних або згенерованих артефактів.

Середня фінансово-технологічна компанія покладалася на спільний мережевий диск для зберігання файлів конфігурації своєї інфраструктури. Інженери підключали диск, відкривали файли у своїх локальних редакторах, вносили зміни та зберігали їх назад у мережу. Одного п’ятничного дня молодший інженер отримав завдання оновити тестове середовище. Помилково він відкрив production-файл payment-processor-deployment.yaml замість тестового варіанта. Він змінив тег образу контейнера на експериментальну збірку, зберіг файл і застосував конфігурацію до кластера.

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

Контроль версій запобігає саме такому сценарію. Git, галузевий стандарт контролю версій, діє як безвідмовна машина часу для вашого коду та конфігурації. Він фіксує кожну зміну, точно визначає, хто її вніс, і дозволяє миттєво повернутися до будь-якого попереднього стану. У сучасному cloud-native світі інфраструктура визначається як код. Якщо ви не можете з абсолютною впевненістю відстежувати, перевіряти та скасовувати свій інфраструктурний код, ви керуєте катастрофою, яка лише чекає свого часу. Опанування Git не є чимось необов’язковим для інженерів платформ; це фундаментальна навичка, на якій будується вся надійна автоматизація та співпраця.

Без Git сучасні конвеєри безперервної інтеграції та безперервного розгортання (CI/CD) не можуть існувати. Вся концепція автоматизованих розгортань спирається на єдине надійне джерело істини, яке запускає автоматизацію щоразу, коли виявляється нова, затверджена зміна. Якщо ви не розумієте Git, ви не зможете зрозуміти сучасний процес постачання програмного забезпечення.

Розділ 1: Концепція контролю версій та архітектура Git

Розділ «Розділ 1: Концепція контролю версій та архітектура Git»

Перш ніж вводити будь-які команди, ви повинні зрозуміти, як Git сприймає ваші файли. Багатьом новачкам важко працювати з Git, оскільки вони ставляться до нього як до простого інструменту резервного копіювання (як Dropbox або Google Drive). Git абсолютно інший. Git не просто постійно синхронізує файли у фоновому режимі; він робить свідомі, незмінні знімки (snapshots) вашого проєкту в певні моменти часу, але лише тоді, коли ви даєте йому явну команду це зробити.

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

Централізований та розподілений контроль версій

Розділ «Централізований та розподілений контроль версій»

Історично системи контролю версій, такі як Subversion (SVN) або Team Foundation Server (TFS), були централізованими. Існував один головний сервер, який зберігав історію. Якщо ви хотіли переглянути історію або зробити коміт (commit), вам потрібно було підключитися до інтернету, щоб зв’язатися з цим сервером. Якщо сервер виходив з ладу, ніхто не міг працювати.

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

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

+---------------------+ +---------------------+ +---------------------+
| | | | | |
| Working Directory | ----> | Staging Area | ----> | Repository |
| (Your local files) | | (The loading dock) | | (The saved history) |
| | | | | |
+---------------------+ +---------------------+ +---------------------+
| | |
| 1. Modify files | |
|---------------------------->| |
| | 2. Group changes |
| |---------------------------->|
| | |
| |
|<----------------------------------------------------------|
3. Restore old versions
  1. Working Directory (Робоча директорія): Це ваш поточний робочий простір на комп’ютері. Він містить фактичні файли, які ви редагуєте, видаляєте або створюєте. Коли ви відкриваєте файл у Vim або VS Code, ви змінюєте Working Directory. Git бачить ці зміни, але ще не зберіг їх.
  2. Staging Area (Індекс): Це вирішальний проміжний крок, унікальний для Git. Уявіть це як вантажну платформу або майданчик для підготовки до фотосесії. Перш ніж зробити остаточний знімок, ви обираєте, які саме змінені файли помістити на цю сцену. Ви можете підготувати одні файли, залишивши інші поза увагою. Це дозволяє створювати вузькоспрямовані, логічні коміти, навіть якщо ви змінили п’ятдесят файлів одночасно.
  3. Repository (Історія комітів): Це постійна база даних, де Git зберігає ваші знімки (які називаються комітами). Коли файли зафіксовано тут, вони надійно записуються в історію з іменем автора, міткою часу та описовим повідомленням. Коміт математично запечатаний; його неможливо таємно змінити, не змінивши його унікальний ідентифікатор.

Активне навчання: Зупиніться та подумайте

Розділ «Активне навчання: Зупиніться та подумайте»

Зупиніться та подумайте: Ви щойно завершили тривалу сесію відлагодження (debugging). Ви виправили помилку підключення до бази даних у db.py, але під час пошуку помилки ви також додали тимчасові виводи (print statements) до auth.py та api.py, які не хочете зберігати назавжди. Як архітектура трьох дерев Git дозволяє створити чисту історію в цьому сценарії, не втрачаючи тимчасовий відлагоджувальний код у робочій директорії?

Перевірка передбачення: Архітектура трьох дерев відокремлює ваші робочі файли від того, що зберігається. Ви можете скористатися Staging Area, щоб вибірково підготувати лише db.py для наступного коміту. Тимчасові виводи в auth.py та api.py безпечно залишатимуться у вашій Working Directory, щоб ви могли продовжувати їх використовувати або видалити пізніше, жодним чином не засмічуючи постійну історію Repository.

Розділ 2: Підготовка: Встановлення та конфігурація

Розділ «Розділ 2: Підготовка: Встановлення та конфігурація»

По суті, Git — це інструмент командного рядка. Хоча графічні інтерфейси існують, вивчення команд термінала є обов’язковим для інженерів платформ, оскільки ви часто будете використовувати Git на віддалених серверах без графічних можливостей. Більшість сучасних дистрибутивів Linux та macOS постачаються з попередньо встановленим Git, або його можна легко додати за допомогою стандартного менеджера пакетів, такого як apt, yum або brew.

Щоб перевірити встановлення, відкрийте термінал і перевірте версію:

Terminal window
git --version

Очікуваний вивід:

git version 2.39.2

Налаштування ідентифікації

Розділ «Налаштування ідентифікації»

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

Ви налаштовуєте це за допомогою команди git config. Прапорець --global застосовує ці налаштування до всіх репозиторіїв на вашому поточному комп’ютері, записуючи їх у прихований файл у вашій домашній директорії (~/.gitconfig).

Terminal window
# Set your name (use your real name, this appears in the history)
git config --global user.name "Alex Chen"
# Set your email address
git config --global user.email "alex.chen@example.com"

Ви можете перевірити свою конфігурацію в будь-який час, попросивши Git вивести список усіх його поточних налаштувань:

Terminal window
git config --list

Ініціалізація репозиторію: git init

Розділ «Ініціалізація репозиторію: git init»

Щоб наказати Git почати відстежувати проєкт, ви повинні ініціалізувати репозиторій у кореневій директорії вашого проєкту. Давайте створимо нову директорію для гіпотетичного проєкту Kubernetes та ініціалізуємо в ній Git.

Terminal window
# Create a new directory
mkdir k8s-webapp
cd k8s-webapp
# Tell Git to start tracking this directory
git init

Очікуваний вивід:

Initialized empty Git repository in /home/alex/k8s-webapp/.git/

Що саме зробила команда git init? Вона не сканувала магічним чином ваш жорсткий диск. Вона просто створила приховану директорію з назвою .git всередині вашої папки k8s-webapp. Ця прихована директорія .git і є фактичним Repository з нашої моделі трьох дерев. Саме тут Git зберігає всі внутрішні об’єкти бази даних, стислі вмісти файлів, граф історії комітів та локальну конфігурацію для цього конкретного проєкту.

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

Terminal window
# List all files, including hidden ones
ls -la

Очікуваний вивід:

total 12
drwxr-xr-x 3 alex alex 4096 Oct 12 10:00 .
drwxr-xr-x 5 alex alex 4096 Oct 12 09:59 ..
drwxr-xr-x 7 alex alex 4096 Oct 12 10:00 .git

З успішно ініціалізованим репозиторієм та налаштованою ідентифікацією ви заклали необхідну основу. Далі ми розглянемо, як наповнити цей репозиторій, свідомо переміщуючи файли через життєвий цикл Git, щоб створити ваші перші зафіксовані знімки (коміти).

Розділ 3: Життєвий цикл знімка: Add, Commit та Status

Розділ «Розділ 3: Життєвий цикл знімка: Add, Commit та Status»

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

Крок 1: Зміна Working Directory

Розділ «Крок 1: Зміна Working Directory»

Давайте створимо наш перший файл — базову конфігурацію простору імен (namespace) Kubernetes.

Terminal window
cat << 'EOF' > namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: webapp-prod
EOF

Виконайте git status, щоб побачити, що Git думає про цей новостворений файл:

Terminal window
git status

Вивід:

On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
namespace.yaml
nothing added to commit but untracked files present (use "git add" to track)

Git розпізнає, що файл існує в Working Directory, але позначає його як “Untracked” (невідстежуваний). Це означає, що Git ніколи раніше не бачив цього файлу. Він не моніторить його на наявність змін і не буде автоматично створювати його резервну копію. Git відстежує лише те, що ви прямо наказуєте йому відстежувати.

Крок 2: Переміщення до Staging Area (git add)

Розділ «Крок 2: Переміщення до Staging Area (git add)»

Щоб повідомити Git, що ми хочемо включити цей файл у наш найперший знімок, ми повинні перемістити його до Staging Area (на вантажну платформу) за допомогою команди git add.

Terminal window
git add namespace.yaml

Знову виконайте git status, щоб спостерігати за зміною стану:

Terminal window
git status

Вивід:

On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: namespace.yaml

Файл перемістився. Тепер він класифікується у розділі “Changes to be committed” (Зміни, що очікують на фіксацію). Він лежить на вантажній платформі, чекаючи, поки фотограф зробить знімок.

Крок 3: Створення знімка (git commit)

Розділ «Крок 3: Створення знімка (git commit)»

Щоб назавжди зберегти підготовлені зміни в Repository, ми використовуємо git commit. Кожен коміт вимагає повідомлення (commit message), яке пояснює, чому була зроблена зміна. Написання хороших повідомлень комітів — це ключова професійна навичка. Хороше повідомлення пояснює намір і контекст, а не лише те, які рядки змінилися.

Terminal window
git commit -m "feat: add production namespace definition"

Вивід:

[main (root-commit) a1b2c3d] feat: add production namespace definition
1 file changed, 4 insertions(+)
create mode 100644 namespace.yaml

Давайте ще раз перевіримо git status, щоб побачити кінцевий результат нашого робочого процесу:

Terminal window
git status

Вивід:

On branch main
nothing to commit, working tree clean

Ваша Working Directory тепер описується як “clean” (чиста). Це означає, що кожен окремий файл, який зараз знаходиться на вашому диску, точно відповідає останньому знімку, збереженому в базі даних .git. Немає жодних змін, що очікують на обробку.

Історія з практики: Випадковий коміт із секретами

Розділ «Історія з практики: Випадковий коміт із секретами»

Молодший розробник локально тестував застосунок, який вимагав ключ доступу AWS. Для зручності він жорстко закодував (hardcoded) ключ безпосередньо у своєму файлі deployment.yaml просто щоб подивитися, чи запустяться поди (pods). Це спрацювало. Зрадівши, він виконав git add . (команду, яка без розбору готує кожен змінений файл у всій директорії), а потім виконав git commit -m "fix deployment".

Після цього він відправив (pushed) код у публічний репозиторій GitHub. За 120 секунд автоматизовані боти безпеки, які сканують публічні репозиторії GitHub, знайшли відкритий ключ AWS. Боти миттєво розгорнули сотні масивних серверів для майнінгу криптовалюти в кількох регіонах AWS, використовуючи скомпрометовані облікові дані. До того моменту, як розробник прокинувся наступного ранку, компанія отримала рахунок за хмарні послуги на суму 65 000 доларів.

Урок: Ніколи сліпо не використовуйте git add ., якщо ви не абсолютно впевнені у тому, що саме змінили. Завжди виконуйте git status та git diff перед додаванням файлів у staging, щоб переконатися, що ви випадково не комітите паролі, API-ключі, приватні SSH-ключі або тимчасові файли для відлагодження.

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

Розділ 4: Подорож у часі: Log та Diff

Розділ «Розділ 4: Подорож у часі: Log та Diff»

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

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

Terminal window
cat << 'EOF' > namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: webapp-prod
labels:
environment: production
EOF

Перегляд змін: git diff

Розділ «Перегляд змін: git diff»

Перш ніж індексувати (stage) або комітити файл, вам завжди слід перевіряти, які саме рядки ви змінили. Пам’ять може підводити; diff є об’єктивним. Команда git diff порівнює ваш поточний робочий каталог з останнім зробленим вами знімком.

Terminal window
git diff

Вивід:

diff --git a/namespace.yaml b/namespace.yaml
index e46b825..8394c41 100644
--- a/namespace.yaml
+++ b/namespace.yaml
@@ -2,3 +2,5 @@ apiVersion: v1
kind: Namespace
metadata:
name: webapp-prod
+ labels:
+ environment: production

Як розшифрувати вивід diff:

  • Заголовки --- a/namespace.yaml та +++ b/namespace.yaml показують дві версії файлів, які порівнюються (стара та нова).
  • @@ -2,3 +2,5 @@ — це заголовок фрагмента (chunk header). Він надає системі контекст щодо того, де приблизно у файлі відбулися зміни.
  • Рядки, що починаються з пробілу, є незміненими рядками контексту. Git показує їх, щоб допомогти вам зорієнтуватися.
  • Рядки, що починаються з + (зазвичай виділені зеленим), є повністю новими доповненнями.
  • Рядки, що починаються з - (зазвичай виділені червоним), є видаленнями. Якщо ви змінили рядок, Git подає це як видалення старого рядка та додавання нового.

Активне навчання: Читання diff

Розділ «Активне навчання: Читання diff»

Зупиніться та подумайте: Уявіть, що ви виконали git diff для файлу Deployment і побачили такий вивід:

@@ -10,3 +10,3 @@
spec:
replicas: 3
- image: nginx:1.14
+ image: nginx:1.24

Перш ніж читати далі, що саме інженер зробив у цьому файлі? Будьте конкретними.

Перевірка передбачення: Інженер не додав повністю нового структурного елемента. Він змінив наявний рядок. Він видалив рядок, що вказував версію контейнера Nginx 1.14, і замінив його рядком із вказівкою на версію 1.24. Це є оновленням версії образу контейнера.

Тепер, коли ми перевірили, що наші зміни правильні та не містять жодних секретів, давайте проіндексуємо та закомітимо додавання нашої мітки:

Terminal window
git add namespace.yaml
git commit -m "chore: add environment label to namespace"

Перегляд історії: git log

Розділ «Перегляд історії: git log»

Щоб побачити часову шкалу ваших знімків, використовуйте команду git log. Вона відкриває пейджер (зазвичай less), який показує вашу історію у зворотному хронологічному порядку (найновіші спочатку).

Terminal window
git log

Вивід:

commit 9f8e7d6c5b4a39281716151413121110abcdef12 (HEAD -> main)
Author: Alex Chen <alex.chen@example.com>
Date: Wed Oct 12 10:45:12 2023 -0400
chore: add environment label to namespace
commit a1b2c3d4e5f60718293a4b5c6d7e8f9012345678
Author: Alex Chen <alex.chen@example.com>
Date: Wed Oct 12 10:15:30 2023 -0400
feat: add production namespace definition

Зверніть увагу на 40-символьні шістнадцяткові рядки, показані вище. У більшості репозиторіїв це хеш коміту, згенерований за допомогою SHA-1. Це математично згенерований унікальний ідентифікатор для конкретного знімка, який відображає вміст файлу, автора, дату та батьківський коміт. Ви можете використовувати цей хеш, щоб перевірити або відновити саме цей момент в історії. Новіші репозиторії також можуть бути налаштовані на використання SHA-256, але приклади в цьому модулі використовують поширений формат SHA-1.

Для більш компактного вигляду, що особливо корисно, коли ви досліджуєте репозиторій із тисячами комітів за кілька років, використовуйте прапорець --oneline:

Terminal window
git log --oneline

Вивід:

9f8e7d6 chore: add environment label to namespace
a1b2c3d feat: add production namespace definition

Ви також можете використати git log -p, щоб побачити фактичні diff, внесені кожним окремим комітом в історії. Це дозволить вам побачити не лише факт створення коміту, але й які саме рядки були ним змінені.

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

Розділ 5: Співпраця зі світом: Remotes, Push та Pull

Розділ «Розділ 5: Співпраця зі світом: Remotes, Push та Pull»

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

Щоб співпрацювати з іншими та створювати резервні копії вашої роботи, ви повинні підключити свій локальний репозиторій до віддаленого сервера, такого як GitHub, GitLab або Bitbucket.

“Remote” (віддалений репозиторій) — це просто ще один Git-репозиторій, розміщений у мережі або в інтернеті. Оскільки Git децентралізований, кожен має повну, автономну копію історії. “Pushing” (відправлення) та “Pulling” (отримання) — це явні дії, які ми виконуємо для синхронізації нашої локальної часової шкали з віддаленою часовою шкалою.

+-----------------------+ +-----------------------+
| | | |
| Local Repository | | Remote Repository |
| (Your Laptop) | | (GitHub/GitLab) |
| | | |
| commit C (HEAD) | ==== git push ===> | commit C |
| commit B | | commit B |
| commit A | <=== git pull ==== | commit A |
| | | |
+-----------------------+ +-----------------------+

Підключення до Remote

Розділ «Підключення до Remote»

Коли ви створюєте порожній репозиторій на такій платформі, як GitHub, платформа надає вам URL-адресу для підключення (зазвичай HTTPS або SSH). Ви вказуєте вашій локальній інсталяції Git підключитися до цієї URL-адреси за допомогою команди git remote add.

За галузевою конвенцією основний віддалений сервер за замовчуванням майже завжди називається origin.

Terminal window
# Example command (do not run unless you have a real repository URL prepared)
git remote add origin https://github.com/yourusername/k8s-webapp.git

Якщо ви приєднуєтеся до компанії та хочете завантажити наявний проєкт, ви не використовуєте git init та git remote add. Натомість ви використовуєте git clone <url>. Клонування автоматично ініціалізує локальний репозиторій, додає remote як origin і завантажує всю історію та файли за один крок.

Відправлення змін (git push)

Розділ «Відправлення змін (git push)»

Щоб завантажити ваші локально створені коміти на віддалений сервер, ви виконуєте “push” (відправляєте їх). Ви повинні вказати ім’я віддаленого репозиторію (зазвичай origin) та назву гілки, яку ви відправляєте (часто main або master).

Terminal window
# Push your main branch to the origin remote for the first time
git push -u origin main

Прапорець -u означає “upstream”. Вам потрібно використовувати його лише під час першого відправлення нової гілки. Він створює постійний зв’язок для відстеження між вашою локальною гілкою main і віддаленою гілкою main. Надалі ви зможете просто вводити git push без жодних аргументів, і Git точно знатиме, куди надсилати дані.

Отримання змін (git pull)

Розділ «Отримання змін (git pull)»

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

Terminal window
# Fetch changes from the remote and merge them into your local branch
git pull origin main

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

Активне навчання: Синхронізація з Remote

Розділ «Активне навчання: Синхронізація з Remote»

Зупиніться та подумайте: Ви провели ранок, працюючи офлайн, і зробили два локальні коміти. Тим часом ваш колега відправив три коміти в ту ж саму гілку на віддаленому сервері. Що станеться, якщо ви наосліп виконаєте git push origin main, коли знову підключитеся до інтернету?

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

Розділ 6: Ігнорування шуму: .gitignore

Розділ «Розділ 6: Ігнорування шуму: .gitignore»

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

  • Скомпільовані бінарні файли, виконувані файли або артефакти збірки (наприклад, .exe, .jar, каталоги /dist/).
  • Файли журналів (логи), згенеровані вашим застосунком під час тестування.
  • Приховані файли операційної системи (наприклад, .DS_Store, згенерований macOS Finder).
  • Секрети, ключі API, паролі до баз даних та локальні змінні середовища (наприклад, файли .env).

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

Давайте створимо файл .gitignore, адаптований для нашого cloud-native середовища.

Terminal window
cat << 'EOF' > .gitignore
# Ignore operating system generated files
.DS_Store
Thumbs.db
# Ignore local secret and credential files
.env
secret-keys.yaml
kubeconfig-local
# Ignore terraform state files (if we add Infrastructure as Code later)
*.tfstate
*.tfstate.backup
.terraform/
EOF

Git читає цей файл зверху вниз. Будь-який файл, що відповідає шаблону, вказаному в .gitignore, ніколи не з’явиться в git status як невідстежуваний (untracked). Це унеможливлює його випадкову індексацію за допомогою команди з підстановкою (wildcard), такої як git add ..

Активне навчання: Зіставлення із шаблоном

Розділ «Активне навчання: Зіставлення із шаблоном»

Зупиніться та подумайте: З огляду на наведений вище файл .gitignore, який із трьох щойно створених файлів все одно відображатиметься як “Untracked” (невідстежуваний), коли ви виконаєте git status? 1) main.tfstate, 2) secret-keys.yaml, 3) secret-keys.txt.

Перевірка передбачення: Лише secret-keys.txt відображатиметься як невідстежуваний. main.tfstate ігнорується правилом підстановки *.tfstate, а secret-keys.yaml явно ігнорується за назвою. secret-keys.txt не відповідає жодному шаблону ігнорування, тому Git і надалі позначатиме його як невідстежуваний файл.

Активне навчання: Запізніле ігнорування

Розділ «Активне навчання: Запізніле ігнорування»

Зупиніться та подумайте: У вас є файл із назвою database-creds.txt, який ви створили минулого тижня. Ви закомітили його в Git кілька днів тому. Сьогодні ви усвідомлюєте свою помилку і додаєте database-creds.txt до свого файлу .gitignore. Ви змінюєте файл облікових даних і виконуєте git status. Чи проігнорує Git зміни?

Перевірка передбачення: Ні, Git не проігнорує зміни. Файл .gitignore лише запобігає додаванню невідстежуваних файлів до бази даних. Щойно файл починає відстежуватися (після коміту), Git продовжуватиме відстежувати його незалежно від того, що вказано в .gitignore. Ви повинні явно вилучити його з відстеження за допомогою команди git rm --cached database-creds.txt, перш ніж правило ігнорування набуде чинності.

  1. Git був створений за два тижні. У 2005 році спільнота розробників ядра Linux раптово втратила безкоштовну ліцензію на пропрієтарну систему контролю версій. Лінусу Торвальдсу, творцю Linux, негайно знадобилася заміна. Не вражений наявними варіантами, він написав початкову версію Git всього за 14 днів, і масивна кодова база ядра Linux мігрувала на неї через два місяці.
  2. Назва є самопринизливою образою. Торвальдс, відомий своїм різким почуттям гумору, назвав систему “Git” (британський сленг, що означає вперту, неприємну або некомпетентну людину). На одній із конференцій він відомо пожартував: “Я егоїстичний виродок, і називаю всі свої проєкти на свою честь. Спочатку Linux, а тепер Git”.
  3. Git не відстежує порожні каталоги. Через базову архітектуру своєї бази даних, яка зіставляє шляхи безпосередньо з вмістом файлів, Git відстежує лише файли. Якщо ви створите порожній каталог і виконаєте git status, Git повністю проігнорує його. Розробники обходять це обмеження, розміщуючи прихований порожній файл (часто умовно названий .gitkeep) всередині каталогу, щоб змусити Git відстежувати існування цієї папки.
  4. Колосальна стійкість до колізій. Хеші, що ідентифікують ваші коміти (рядки SHA-1), є 40-символьними шістнадцятковими числами. Математична ймовірність того, що два різні знімки згенерують абсолютно однаковий хеш (колізія хешів), астрономічно низька. За статистикою, набагато ймовірніше, що в вас влучить блискавка одночасно з виграшем у лотерею, ніж ви зіткнетеся з випадковою колізією хешів Git у вашому репозиторії.
ПомилкаЧому це трапляєтьсяЯк це виправити
Випадковий коміт пароля/секретуВикористання невибіркової команди git add . без попередньої перевірки git status, що випадково затягує файл .env до Staging Area.Якщо не відправлено (unpushed): git reset HEAD~1, щоб скасувати коміт локально. Якщо відправлено (pushed), секрет скомпрометовано. Ви повинні негайно відкликати/змінити облікові дані в AWS/GCP. Не просто видаляйте їх у новому коміті; історія залишається назавжди.
”fatal: refusing to merge unrelated histories”Ви ініціалізували репозиторій локально, а також ініціалізували окремий репозиторій на GitHub зі стандартним файлом README, після чого спробували виконати pull. Git вважає, що це два абсолютно різні, непов’язані проєкти.Виконайте git pull origin main --allow-unrelated-histories, щоб примусово вказати Git об’єднати дві різні часові лінії в одну.
”Updates were rejected because the remote contains work that you do not have locally”Ваш колега відправив нові коміти на сервер GitHub, поки ви перебували офлайн. Git не дозволяє вам виконати push і перезаписати їхню роботу.Спочатку виконайте git pull, щоб завантажити та інтегрувати їхні зміни у вашу локальну гілку. Вирішіть усі можливі конфлікти злиття (merge conflicts), а потім виконайте git push.
Порожні або беззмістовні повідомлення комітівПоспіх у роботі. Використання розмитих повідомлень на кшталт git commit -m "update" або git commit -m "fixed stuff".Використайте git commit --amend -m "new better message", якщо ви ще не виконали push. Виробіть професійну звичку писати “Чому”, а не лише “Що”.
Забули додати файли до Staging Area перед комітомВиконання команди git commit -m "message", коли ваші зміни все ще знаходяться у Working Directory, повністю оминаючи Staging Area.Виконайте git status, щоб побачити, що не додано до Staging Area (unstaged). Виконайте git add <file>, щоб перемістити зміни на stage, а потім повторіть команду git commit.
Коміт величезних бінарних файлівВипадкове додавання скомпільованих артефактів, дампів пам’яті бази даних або великих відео до репозиторію. Git розроблений для відстеження тексту, а не великих бінарних файлів.Видаліть файл з бази даних відстеження за допомогою команди git rm --cached <file>, зафіксуйте видалення комітом і негайно додайте цей тип файлів до вашого .gitignore.

Контрольні запитання

Розділ «Контрольні запитання»
1. Ваша команда щойно розгорнула нову конфігурацію Kubernetes, і кластер одразу ж вийшов з ладу. Вам потрібно швидко дізнатися, хто вніс останню зміну та яким було повідомлення цього коміту. Яку команду ви виконаєте? Вам слід виконати `git log` або `git log --oneline`. Ця команда відображає історію комітів у зворотному хронологічному порядку, показуючи автора, мітку часу та повідомлення коміту для кожного знімка (snapshot). Проаналізувавши цей результат, ви можете миттєво визначити, хто вніс останні зміни, та прочитати їхнє пояснення того, чому ця зміна була необхідною. Саме можливість швидко переглянути історію робить контроль версій критично важливим під час інцидентів у продакшені (production).
2. Ви змінили файл `service.yaml` на своєму ноутбуці, щоб відкрити новий порт. Ви вводите `git commit -m "expose port 8080"`, але Git повертає повідомлення "nothing added to commit but untracked files present". Що ви забули зробити? Ви забули перемістити файл з Working Directory до Staging Area за допомогою команди `git add`. Архітектура Git вимагає від вас явно вказувати, які файли мають бути включені до наступного знімка. Оскільки ви оминули Staging Area, Git побачив ваш змінений файл, але відмовився автоматично додавати його до репозиторію. Вам необхідно виконати `git add service.yaml` перед наступною спробою зробити коміт.
3. Ви збираєтеся додати `configMap.yaml` до Staging Area, але не можете згадати, чи встановили тестовий пароль до бази даних, чи залишили там пароль від продакшену. Яку команду вам слід виконати, щоб перевірити точні рядки, які ви змінили, перед додаванням на stage? Вам слід виконати `git diff`, щоб переглянути точні зміни по рядках. Ця команда порівнює вашу поточну Working Directory з останнім збереженим знімком у репозиторії. Вона відобразить видалені рядки червоним кольором, а додані — зеленим, дозволяючи вам об'єктивно перевірити вміст файлу. Використання цієї команди запобігає випадковому коміту секретів від продакшену в постійний граф історії.
4. Ви щойно приєдналися до нового проєкту. Ви клонуєте репозиторій і виявляєте, що Git не знає ваших `user.name` та `user.email`, тому він просить вас виконати `git config` перед комітом. Чому це необхідно, і чим це відрізняється від запитів на автентифікацію, які ви можете побачити під час `git push`? Git вимагає ідентифікації автора під час створення коміту, тому `user.name` та `user.email` мають бути налаштовані до того, як `git commit` зможе записати, хто є автором знімка. Ця ідентичність зберігається в метаданих коміту для підзвітності та відстеження. Натомість запити під час `git push` — це зазвичай перевірки віддаленої автентифікації від сервісу хостингу, такі як помічник облікових даних HTTPS, особистий токен доступу (personal access token) або SSH-ключі. Коротко кажучи: ідентичність для коміту — це локальні метадані для `git commit`; автентифікація під час push доводить, що вам дозволено завантажувати дані на віддалений сервер (remote).
5. Ви створили файл з назвою `aws-credentials.json` на своїй локальній машині для тестування скрипта. Ви ніколи не хочете, щоб цей файл потрапив до корпоративного репозиторію. Що саме вам слід зробити, щоб гарантувати, що він ігноруватиметься назавжди? Ви повинні створити звичайний текстовий файл з назвою `.gitignore` у корені вашого репозиторію, якщо він ще не існує. Усередині цього файлу потрібно додати точну назву `aws-credentials.json` з нового рядка. Git читає цей конфігураційний файл зверху вниз і автоматично відфільтровує будь-які файли, що збігаються, зі своїх радарів відстеження. Це гарантує, що файл з обліковими даними ніколи не буде випадково доданий до Staging Area або закомічений, що запобігає серйозному порушенню безпеки.
6. Молодший розробник намагається "скинути" зламаний проєкт, щоб почати все спочатку. Він відкриває свій файловий менеджер, видаляє приховану папку `.git`, а потім вводить `git status` у терміналі, очікуючи, що Git зрозуміє, що проєкт було скинуто, і покаже порожню історію. Що відбувається насправді і чому? Коли розробник вводить `git status`, термінал поверне помилку "fatal: not a git repository", оскільки він повністю знищив систему контролю версій для цієї папки. Прихована директорія `.git` — це не просто конфігураційний файл; це вся фактична база даних репозиторію, що містить усі коміти, гілки та історичні знімки. Видаливши її, він не скинув історію — він назавжди стер її локально, перетворивши свій проєкт назад на звичайну, невідстежувану папку у своїй операційній системі. Робочі файли на його диску залишаються незмінними, але Git ними більше не керує.
7. Ви та ваш колега одночасно змінюєте один і той самий файл `nginx-deployment.yaml`. Він відправляє зміну, яка встановлює `replicas: 5`, поки ви перебуваєте офлайн. Ви локально змінюєте цей самий рядок на `replicas: 2` і намагаєтесь виконати push. Git відхиляє ваш push, тому ви виконуєте `git pull`. Що відбувається далі і як це вирішити? Git спробує автоматично об'єднати зміни, але оскільки ви обидва змінили один і той самий рядок, він зупиниться і повідомить про конфлікт злиття (merge conflict). Він не може безпечно вгадати, чи повинен Deployment мати 5 реплік або 2, тому залишає рішення за людиною. Щоб вирішити конфлікт, ви повинні відкрити файл у своєму редакторі та знайти маркери конфлікту (які виглядають як `<<<<<<< HEAD` та `>>>>>>>`). Після ручного редагування файлу до бажаного стану та видалення маркерів, вам потрібно використати `git add` та `git commit`, щоб завершити злиття перед виконанням push.

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

Завдання 1: Ініціалізація

Розділ «Завдання 1: Ініціалізація»

Створіть нову директорію з назвою dojo-k8s-project і перейдіть до неї. Ініціалізуйте порожній репозиторій Git.

  • Директорія створена, і ви перейшли до неї.
  • Репозиторій Git ініціалізовано.
Рішення: Завдання 1
Terminal window
mkdir dojo-k8s-project
cd dojo-k8s-project
git init
git status

Завдання 2: Перший коміт

Розділ «Завдання 2: Перший коміт»

Створіть файл README.md із текстом ”# KubeDojo Project”. Додайте файл до Staging Area і зафіксуйте його (коміт) із повідомленням “docs: add initial readme”.

  • Файл створено з правильним вмістом.
  • Файл додано до Staging Area.
  • Коміт успішно створено.
Рішення: Завдання 2
Terminal window
echo "# KubeDojo Project" > README.md
git status
git add README.md
git status
git commit -m "docs: add initial readme"

Завдання 3: Імітація розробки інфраструктури

Розділ «Завдання 3: Імітація розробки інфраструктури»

Створіть файл з назвою deployment.yaml і додайте наступний фіктивний вміст:

apiVersion: apps/v1
kind: Deployment
metadata:
name: web

Додайте до Staging Area та закомітьте цей файл із повідомленням “feat: add web deployment skeleton”.

  • Файл створено.
  • Коміт успішно створено з правильним повідомленням.
Рішення: Завдання 3
Terminal window
cat << 'EOF' > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
EOF
git status
git add deployment.yaml
git commit -m "feat: add web deployment skeleton"

Завдання 4: Зміна існуючих файлів

Розділ «Завдання 4: Зміна існуючих файлів»

Відкрийте deployment.yaml і додайте replicas: 3 у блок spec:, щоб він виглядав так:

apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3

Використайте команду для перегляду точних відмінностей перед додаванням на stage. Потім додайте зміну до Staging Area та закомітьте з повідомленням “fix: set deployment replicas to 3”.

  • Файл змінено.
  • Відмінності (diff) успішно переглянуто.
  • Зміну додано до Staging Area та закомічено.
Рішення: Завдання 4
Terminal window
# Змініть файл за допомогою вашого улюбленого редактора (nano, vim або cat override)
cat << 'EOF' > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
EOF
# Перегляд відмінностей
git diff
# Додавання до Staging Area та коміт
git add deployment.yaml
git commit -m "fix: set deployment replicas to 3"

Завдання 5: Огляд історії

Розділ «Завдання 5: Огляд історії»

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

  • Команду історії виконано.
  • У результатах видно три окремі коміти.
Рішення: Завдання 5
Terminal window
git log --oneline

Вивід має виглядати приблизно так:

3b2a1c4 fix: set deployment replicas to 3
9f8e7d6 feat: add web deployment skeleton
1a2b3c4 docs: add initial readme

Завдання 6: Бонусний виклик — розширені правила ігнорування

Розділ «Завдання 6: Бонусний виклик — розширені правила ігнорування»

Ви працюєте над новим застосунком, який генерує численні лог-файли із закінченням .log у різних директоріях. Ви хочете, щоб Git ігнорував їх усі задля економії місця, але ви повинні гарантувати, що один конкретний файл з назвою audit-trail.log у кореневій директорії завжди відстежуватиметься з міркувань відповідності нормативним вимогам. Створіть файл .gitignore, який реалізує саме цю конфігурацію. Перевірте своє рішення, створивши фіктивні файли (наприклад, app.log, database.log та audit-trail.log) і перевіривши git status, щоб переконатися, що лише audit-trail.log готовий до відстеження.

  • Файл .gitignore створено з відповідними правилами використання шаблонів (wildcard) та виключень.
  • Фіктивні файли створено для перевірки правил.
  • git status підтверджує, що лише потрібний файл є невідстежуваним (untracked).
Рішення: Завдання 6
Terminal window
# Створення файлу .gitignore
cat << 'EOF' > .gitignore
*.log
!audit-trail.log
EOF
# Створення фіктивних файлів
touch app.log
touch database.log
touch audit-trail.log
# Перевірка статусу
git status

Git покаже .gitignore та audit-trail.log як невідстежувані (untracked) файли. Інші файли .log будуть успішно проігноровані.


Наступний модуль: Модуль 0.7: Що таке мережі? — Тепер, коли ви можете відстежувати файли, час зрозуміти, як комп’ютери насправді спілкуються один з одним через мережу.