1 of 30

Git

Система керування версіями

2 of 30

План

  • Базові поняття
  • Створення репозиторію
  • Операції Git при внесенні змін
  • Робота з гілками
  • Запити на злиття гілки
  • Видалення гілки
  • Коміти злиття
  • Конфлікти злиття та їх вирішення
  • Виключення відстеження файлів
  • Збереження незавершених змін (git stash)
  • Навігація по історії
  • Скасування або внесення змін до вже зроблених комітів
  • Злиття гілок (у власну гілку)

3 of 30

Призначення Git – спільна робота над одним проєктом

  • робота над одним і тим же кодом;
  • централізоване сховище – віддалений репозиторій;
  • власна копія коду – локальний репозиторій;
  • автоматизація застосування змін;
  • повідомлення про конфлікти;
  • неперервна інтеграція як краща практика;
  • повернення до попередніх версій;
  • фіксація змін (коміти), повідомлення, історія комітів

4 of 30

Базові поняття Git

  • віддалений репозиторій;
  • локальний репозиторій;
  • історія змін (git log);
  • індекс Git (область додавання) – інформація, що буде збережено в наступному коміті;
  • Git-клієнт (CLI, GUI)

5 of 30

Варіанти створення Git-репозиторію

  • Хмарна платформа (GitHub, GitLab);
  • Власний сервер (Bitbucket, DigitalOcean)

Репозиторії можна робити приватними або публічними

6 of 30

Варіанти створення локального репозиторію

  • Клонування віддаленого репозиторію;
  • Ініціалізації локального репозиторію.

7 of 30

Варіант 1. Створення та клонування віддаленого репозиторію

  • Крок 1. Реєстрація на GitLab;
  • Крок 2. Створення віддаленого репозиторію;
  • Крок 3. Установка Git-клієнта на локальну машину;
  • Крок 4. Локальні налаштування Git;

git config --global user.name "firstName lastName"

git config --global user.email "yourEmail@gmail.com"

  • Крок 5. Аутентифікація. Хороша практика – SSH-аутентифікація;
  • Крок 6. Клонування

git clone git@gitlab.com:<UserName>/myproject.git

  • Крок 7. Створюємо та перемикаємось на гілку main.
  • git switch -c main
  • Крок 8. Виводимо ім’я поточної гілки
  • git branch --show-current

8 of 30

Варіант 2. Ініціалізація локального репозиторію

  1. Створюємо віддалений репозиторій (наприклад, DemoNodeJSApp)
  2. В корені проекту ініціюємо локальний репозиторій
  3. Для локального репозиторію додаємо інформацію про віддалений репозиторій
  4. Робимо відправку коду з локального репозиторію на віддалений

9 of 30

Серія команд для ініціалізації локального репозиторію

cd projects/DemoNodeJSApp – змінюємо робочу папку на DemoNodeJSApp

git init – створюємо локальний репозиторій

git checkout -b main – створюємо та робимо поточною гілку main

git remote add origin git@gitlab.com:<UserName>/demo-nodejs-app.git – додаємо інформацію про віддалений репозиторій. Origin – ім’я, що використовується для посилання на віддалений репозиторій.

10 of 30

Операції Git

11 of 30

Основний цикл роботи з Git при внесенні змін

  • cd projects/myproject – змінюємо робочу папку на myproject.
  • git switch -c main – створюємо та перемикаємось на гілку main.
  • git branch --show-current – виводимо ім’я поточної гілки.
  • touch README.md – створюємо файл README.md.
  • git status – переглянемо статус локального репозиторію. При цьому файл README.md буде в списку невідстежуваих файлів.
  • git add README.md – додаємо файл README.md в Git-індекс.
  • git status – знову переглянемо статус локального репозиторію. Файл README.md вже буде в списку файлів, готових до фіксації.
  • git commit -m "add README" – фіксуємо зміни.
  • git push -u origin main – відправляємо зафіксовані зміни на віддалений репозиторій origin в гілку main.
  • git log – перегляд історії змін в локальному репозиторії.

12 of 30

Робота з гілками Git

  • створення нових функцій, виправлення помилок: для кожної функції своя гілка;
  • злиття власної гілки з основною;
  • конфлікти при злитті;
  • головна гілка повинна бути завжди готовою до випуску;
  • іменування гілок у відповідності до стандартів: feature/user-auth, bugfix/user-auth-error

13 of 30

Створення гілки на віддаленому репозиторії

  • Крок 1. branches -> New Branch;
  • Ім’я гілки -> створити з гілки Main;
  • Передамо інформацію про нову гілку на локальний репозиторій:

git pull – передаємо зміни з віддаленого на локальний репозиторій

git checkout bugfix/user-auth-error – перемикаємось на гілку bugfix/user-auth-error

git branch – виводимо інформацію про наявні гілки та поточну гілку

14 of 30

Створення гілки через термінал

Крок 1. Виконаємо команди для створення нової гілки:

git checkout main – перемикаємось на головну гілку

git checkout -b feature/database-connection – створюємо нову гілку з гілки main, перемикаємось на неї

Крок 2. Для прикладу створимо файл connect.js з виводом рядка “Connection to DB”.

Крок 3. Робимо відправку на віддалений репозиторій:

git add . – додаємо всі змінені файли в Git-індекс

git commit -m "Connect to DB feature" – фіксуємо зміни

git push --set-upstream origin feature/database-connection – відправляємо на віддалений репозиторій нову гілку та коміт, зроблений в ній.

15 of 30

На практиці

16 of 30

Запити на злиття гілки

Щоб включити зміни з вихідної гілки в цільову гілку, хорошою практикою є запит на злиття (MR).

При відкритті запиту на злиття, можна вивести зміни та спільно працювати над ними до безпосереднього злиття. Запити на злиття включають:

  • Опис запиту.
  • Зміни коду та перегляд вбудованого коду.
  • Інформація про конвеєри CI/CD.
  • Розділ коментарів для дискусій.
  • Список комітів.

17 of 30

Запити на злиття

Крок 1. Клацнемо branches. В гілці, яку потрібно злити з головною, клацнемо Merge Request.

Крок 2. Задамо заголовок та опис запиту на злиття. Також поля “assignee” та “reviewer”.

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

18 of 30

Видалення гілок

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

# Перемикаємось на гілку main

git checkout main

# Отримуємо зміни по злиттю

git pull

# Отримуємо інформацію про всі віддалені репозиторії, зокрема інформацію про видалені гілки на віддалених репозиторіях

git fetch --all --prune

# Вивести список гілок для визначення, які гілки видалені (gone)

git branch -vv

# Видалити потрібну гілку з локального репозиторію

git branch -D feature/database-connection

19 of 30

Коміти злиття

Припустимо, що в нас є локальний репозиторій. Ми зробили коміт, але відправку зробити не можемо, оскільки на віддаленому репозиторії інший користувач відправив новий коміт. Система запропонує спочатку отримати зміни:

git pull

В такому випадку додатково створюється так званий merge-коміт (коміт злиття віддаленої та локальної гілки). При наступній відправці змін з локального репозиторію вже відправиться два коміти:

20 of 30

Виключення даних про коміти злиття з віддаленого репозиторію

Крок 1. Робимо коміт локальних змін.

Крок 2. Виконуємо git pull --rebase <remote-name> <branch-name

По суті, rebase спочатку видаляє наші коміти, які ми зробили на поточній гілці. Потім він застосує всі віддалені коміти, а потім застосує наші коміти поверх.

Крок 3. Відправляємо коміти на віддалений репозиторій: git push

21 of 30

Конфлікти злиття

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

CONFLICT (content): Merge conflict in <fileName>

Automatic merge failed; fix conflicts and then commit the result.

При цьому код матиме вигляд:

22 of 30

Вирішення конфліктів злиття. Інструмент Resolve Merge Conflict

Вирішивши даний конфлікт, зробимо новий коміт та здійснимо відправку на віддалений репозиторій.

23 of 30

Файли, що не потрібно відстежувати

  • Службові папки середовища розробки (.idea для WebStorm тощо);
  • Папка build зі збіркою застосунку;
  • Папка з залежностями (node_modules для NodeJS-застосунку);
  • Локальні файли з конфігурацією з’єднання, обліковими даними тощо.

24 of 30

Виключення відстеження заданих файлів (.gitignore)

Крок 1. Створимо файл .gitignore та додамо в нього такі файли та папки:

node_modules/*

.idea/*

build/*

Крок 2. Зважаючи на те, що папка node_modules продовжує знаходитись в репозиторії, потрібно її видалити з репозиторію, залишивши локально:

git rm -r --cached node_modules

Крок 3. Робимо додавання змін в Git-індекс, фіксацію та віправку в поточну гілку:

git add .

git commit -m "Added .gitignore"

git push

Переконуємось в наявності файлу .gitignore і що папка node_modules видалена з усім її вмістом на віддаленому репозиторії.

25 of 30

Збереження незавершених змін (git stash)

При спробі виконати команду git checkout main, якщо не зроблений коміт, система повідомить про помилку і не перемикне гілку.

Для можливості перемикання на іншу гілку із збереженням незавершених змін без необхідності робити коміт потрібно виконати команду:

git stash

Потім знову перейти в дану гілку і повернути зроблені зміни назад:

git stash pop

26 of 30

Навігація по історії

Для виводу історії комітів можна виконати команду

git log

При потребі можна повернутись до стану будь-якого попереднього коміту (наприклад, якщо потрібно відслідкувати помилку). Для цього виконаємо команду:

git checkout <commit_hash>

Для повернення до попередньої точки HEAD (останній коміт поточної гілки) виконаємо команду:

git checkout -

27 of 30

Скасування або внесення змін до вже зроблених комітів

git reset --hard HEAD~1

HEAD – вказівник на верхній коміт, 1 – кількість комітів, що скасовується. Параметр --hard відміняє і коміт і самі зміни в проекті. Якщо зміни потрібно залишити для подальшої роботи з ними, вказуємо параметр --soft (по замовчуванню).

Якщо поточні зміни потрібно додати в уже виконаний останній коміт, це можна зробити командою:

git commit --amend

Для скасування коміту на віддаленому репозиторії після відповідної дії на локальному, необхідно виконати команду:

git push --force

Для скасування коміту в головній гілці необхідно виконати команду:

git revert <commit_hash>

28 of 30

Злиття гілок

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

29 of 30

Для злиття комітів з головної гілки у власну гілку, виконаємо такі команди

# Змінюємо поточну гілку на features

git checkout features

# Зливаємо коміти в поточну гілку з головної гілки

git merge main

# Переглядаємо історію і переконуємось, що останній коміт – злиття гілки main в гілку features

git log

# Відправляємо зміни щодо злиття на віддалений репозиторій

git push

30 of 30

Роль Git в CI/CD

  • репозиторії для керування інфраструктурою як кодом, наприклад для для зберігання та постачання конфігурацій, виконуваних скриптів, сценаріїв розгортання та інших ресурсів (Kubernetes, Terraform, Ansible, bash-скрипти або Python-скрипти тощо)
  • при роботі з інструментами для автоматизації збірки застосунків, конвеєрами для CI/CD