До списку уроків
9 клас · Урок 14 з 16

Команда і Gitea: гілки, PR, код-рев’ю, каркас сайту

виконано0%
Крок 1

Що робимо сьогодні

Модуль I · Хмарні сервіси й документи · тема 8, урок 1 з 2 · 120 хвилин

Після уроку ти вмієш

Далі на сторінці трапляться слова «репозиторій», «коміт», «гілка», «pull request» і «конфлікт злиття». Поки вони нічого не означають. Розберемо їх по черзі.

Тринадцять уроків ти працював сам: свій акаунт, своя тека ~/www/, свій FTP-клієнт. Сьогодні все змінюється. У вас одна тека на трьох-чотирьох, і кожен правитиме в ній файли одночасно з рештою.

Мета. Працювати в спільній теці так, щоб чужі зміни не затирали твої. Для цього є звичний порядок: гілка, коміт, pull request, рев’ю, злиття. А ще ви зверстаєте каркас командного сайту. Це чотири сторінки зі спільною навігацією й одним файлом стилів.

Єдиний урок теми, де здача йде не по FTP Тут файли потрапляють на сайт не через FileZilla. Ти віддаєш зміни командою git push — і сервер сам розкладає файли й оновлює https://team<N>.<домен>/. FTP лишається тільки для особистого дзеркала в ~/www/team/.

Де живе твій репозиторій

Уяви спільну шафу для файлів команди, ключ від якої є в кожного. У класі така шафа справді є. Це Gitea — сервер git на нашому власному VPS.

Він робить те саме, що GitHub: сторінка проєкту, гілки, заявки на злиття, коментарі до коду. Різниця одна — він наш. Твої файли не виходять за межі шкільного сервера. І акаунт той самий, що й для SSH.

КласОрганізація в GiteaТвій репозиторійСайт команди
9-Аclass9aclass9a/team-Nteam<N>.<домен>
9-Бclass9bclass9b/team-Nteam<N>.<домен>

Хід уроку

ЕтапХвЩо робимо
Формування команд15Ролі, спільний список задач, ознаки готовності
Теорія: git і три місця файлу20Граф комітів, add/commit/push
Перший коміт і PR20Клон, гілка, коміт, push, pull request у Gitea
Конфлікт злиття15Тренажер git: свідомо ламаємо й лагодимо
Код-рев’ю15Тренажер: три фрагменти, чотири коментарі
Практика: каркас сайту30Чотири сторінки, спільний <nav>, один CSS
Підсумок5Картка здоров’я команди з Gitea API
Разом120
Що здає команда Репозиторій class9a/team-N (або class9b/team-N) з чотирма сторінками, одним файлом стилів, README.md і CONTRIB.md; щонайменше один злитий pull request; у кожного учасника — свої коміти під своїм акаунтом. Сайт відкривається за адресою команди.
Крок 2

Навіщо взагалі git

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

Уяви теку командного проєкту без git. У ній лежить це:

тека без git
$ ls index.html index_нова.html index_фінал.html index_фінал_2.html index_фінал_2_ОСТАННЯ.html index_Оксана.html index_правки_Дениса.html style.css style_new.css style_ВИКОРИСТОВУВАТИ_ЦЕЙ.css

Це не жарт. Так виглядає майже кожен спільний проєкт без системи контролю версій. І головне питання тут навіть не «де потрібний файл». Питання інше: що змінилося між фінал і фінал_2 і хто це зробив. Відповіді немає в жодного з учасників.

Що дає git

ЗадачаБез gitЗ git
Історія змін копії файлів із датами в назві git log: хто, коли, що і навіщо — по кожному рядку
Відкотитися «у когось був бекап позавчора?» будь-який стан проєкту повертається однією командою
Двоє в одному файлі той, хто зберіг другим, затер першого git зливає обидві зміни; якщо не може — зупиняється й питає
Хто автор рядка ніхто не знає git blame показує коміт і автора кожного рядка

Після git clone у тебе на комп’ютері лежить повна історія проєкту. Не шматок, а вся — від найпершого коміту. Саме тому git звуть розподіленою системою контролю версій.

Через це git log працює навіть без мережі. А Gitea — це не «головний git». Це просто спільна точка обміну для всієї команди.

Питання

Твоя команда домовилася обмінюватися файлами через спільну теку в хмарі: хто закінчив — той залив. О 14:20 ти зберіг style.css, о 14:22 те саме зробила Оксана зі своєї копії. Що станеться з твоїми змінами і чим тут допоміг би git?

Крок 3

Три місця, де живе твій файл

Це найважливіша схема уроку. Половина «незрозумілих» помилок git — це нерозуміння, у якому з трьох місць зараз файл

Коли ти правиш HTML у звичайному редакторі, файл існує в одному місці — на диску. У git місць три, і файл проходить їх по черзі.

Робоча тека Індекс Репозиторій Сервер Gitea файли, які ти бачиш і правиш що піде в наступний коміт тека .git уся історія, локально class9a/team-3 спільна для всіх git add git commit git push git clone (перший раз) · git pull (щоразу далі) Файл, який ти змінив, але не зробив git add, у коміт НЕ потрапить — він лишиться тільки в робочій теці, на твоєму комп’ютері.
Три місця файлу і команди, що переносять його між ними. Стрілка праворуч — це шлях твоєї роботи до команди; пунктир ліворуч — шлях чужої роботи до тебе.

Базовий цикл: п’ять команд

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

базовий цикл
$ git clone https://git.<домен>/<клас>/<команда>.git # отримав повну копію репозиторію разом з усією історією $ git status # що змінено, що в індексі, на якій я гілці $ git add index.html # поклав файл в індекс — сказав «це піде в коміт» $ git commit -m "Додати навігацію на всі чотири сторінки" [feature-nav 3a91c7d] Додати навігацію на всі чотири сторінки 4 files changed, 12 insertions(+), 4 deletions(-) $ git push # відправив коміти на Gitea

git status — головна команда новачка. Вона показує те, чого не видно очима. А саме: у якому з трьох місць зараз твої зміни. Запускай її після кожної дії. Скоро почнеш вгадувати відповідь наперед — і це добра ознака.

Чому add і commit — це два кроки, а не один Індекс дозволяє зібрати коміт із частини змін. Ти правив три файли, але готовий один — git add лише його, закомітив, а решта спокійно чекає в робочій теці. Коміт має бути про одну зміну, а не «все, що я встиг за годину».
Питання

Ти створив index.html і style.css. Потім набрав git commit -m "Каркас головної". Git відповів: nothing added to commit but untracked files present. У якому з трьох місць зараз твої зміни і що ти набереш наступним рядком?

Питання

Ти зробив коміт о 14:30. О 14:45 тимлід каже: на сайті команди твоїх змін не видно. Ти перевірив — git log показує твій коміт першим рядком. Де застрягла робота?

Крок 4

Повідомлення коміту: що писати в рядку після -m

Найдешевша річ, яку можна зробити для команди, — і та, на якій економлять найчастіше

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

ПоганоЧому поганоДобре
фіксщо саме зламалося? де? Виправити шлях до style.css на story.html
ще разнічого не каже взагалі Додати посилання на data.html у навігацію
зміникоміт завжди про зміни Прибрати дубль CSS із чотирьох сторінок
.класика ліні Зверстати підвал з іменами команди

Правило одного рядка

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

коміт із тілом повідомлення
$ git commit # відкриється редактор; набираєш: Винести навігацію в один блок на всіх сторінках Навігація була скопійована в чотири файли, і після додавання data.html три з них розійшлися. Тепер блок однаковий скрізь, правка робиться в одному місці.

Наказова форма — не примха. Її обрали тому, що git сам пише повідомлення в такому ж стилі: Merge branch 'feature-nav', Revert "Додати підвал". Коміт відповідає на питання «що зробить проєкт, якщо я його застосую».

Питання

Через три тижні сайт команди перестав показувати стилі. Ти відкриваєш git log --oneline і бачиш двадцять комітів. Вісім із них називаються «фікс», п’ять — «ще раз», решта осмислені. Скільки часу забере пошук винного коміту? І що треба було робити раніше, щоб пошук зайняв хвилину?

Крок 5

Гілки: як четверо працюють і не заважають одне одному

Гілка — це не копія теки. Це рухома закладка на коміті

У репозиторії є головна гілка — main. Саме з неї сервер бере файли й публікує сайт команди. Робить він це сам, щойно в гілці з’являється новий коміт. Такий автоматичний сигнал зветься webhook.

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

Тому кожен робить свою роботу в окремій гілці. Гілка відгалужується від main і живе кілька годин або днів. Коли робота готова й перевірена, вона зливається назад.

каркас стилі підвал тексти злиття nav 1 nav 2 main feature-nav точка розгалуження коміт злиття: два батьки → сайт команди
Гілка feature-nav відгалузилася від main після коміту «стилі», прожила два коміти й повернулася злиттям. Поки вона жила, у main устигли зайти ще два чужі коміти — і це нормально.

Як зробити гілку

гілки
$ git switch -c feature-nav Switched to a new branch 'feature-nav' $ git branch * feature-nav main $ git switch main Switched to branch 'main'

Стара форма тієї самої команди — git checkout -b feature-nav. Вона працює скрізь і досі трапляється в інструкціях. Але git switch зрозуміліший: він робить одну річ, а не сім.

Як називати гілки

Що таке злиття Злиття (merge) — це коміт, у якого два батьки: останній коміт main і останній коміт твоєї гілки. Git бере обидва набори змін і складає їх в один результат. Якщо ви правили різні файли або різні рядки — він робить це сам, мовчки. Якщо той самий рядок — зупиняється і питає тебе.
Питання

Твоя команда домовилася: усі працюємо в main, «щоб не плутатися з гілками». Через двадцять хвилин сайт команди відкривається з поламаною версткою. Виправити її не встигають: кожен новий push ламає щось іще. Назви дві різні проблеми, які створила ця домовленість.

Крок 6

Пісочниця: збери дерево комітів руками

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

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

Нижче — справжня модель git у мініатюрі. У ній один файл index.html і три рядки, які можна правити. Цикл повний: правка, add, commit, гілка, злиття. Дерево комітів малюється саме́.

Як спровокувати конфлікт. Змінити той самий рядок у двох різних гілках і спробувати їх злити. Кнопка «Створити конфлікт» робить це за тебе в чотири кроки — але цікавіше зібрати руками.

Симулятор гілок і конфліктів
гілка
правити рядок
git
злити в поточну

index.html у робочій теці гілки main

Що тут спрощено У справжньому git коміт зберігає весь стан проєкту, а хеш рахується з вмісту — тому він виглядає як 3a91c7d і його не можна вгадати. У пісочниці хеші вигадані для наочності, файл один, а рядків для правки три. Уся решта логіки — справжня: індекс, батьки комітів, пошук спільного предка, fast-forward, маркери конфлікту.
Питання

У пісочниці ти створив гілку й зробив у ній коміт. Потім злив її в main, де відтоді нічого не мінялося. Git написав Fast-forward і не створив коміт злиття. Чому в цьому випадку коміт злиття не потрібен?

Крок 7

Pull request: попросити влити свою роботу

Технічно злиття робиться однією командою. PR потрібен, щоб перед злиттям на код подивилася людина

Ти закінчив роботу у своїй гілці. Тепер треба сказати команді: «я зробив навігацію в гілці feature-nav, візьміть її в main». Таке прохання пишуть не в чаті, а окремою сторінкою прямо в Gitea.

Ця сторінка зветься pull request. У Gitea і GitHub її скорочують до двох літер — PR.

Заявку видно всій команді. Під нею пишуть коментарі до конкретних рядків. А кнопка «Merge» вмикається тільки тоді, коли хтось підтвердив рев’ю.

гілка + коміти git push PR відкрито рев’ю merge feature-nav гілка на сервері опис: що і навіщо коментарі до рядків гілка вливається зауваження → нові коміти в ту саму гілку → PR оновлюється сам webhook сайт оновився PR не «зберігає» код — код уже на сервері після push. PR вирішує, чи потрапить він у main.
Шлях pull request від першого коміту до оновленого сайту. Зворотна стрілка — найважливіша частина: PR не переробляють з нуля, у нього просто дописують коміти.

Що писати в описі PR

Опис читає людина, яка не сиділа поруч, коли ти це робив. Три речення економлять їй десять хвилин:

повний шлях: від гілки до PR
$ git switch -c feature-nav $ git add index.html story.html media.html data.html $ git commit -m "Додати спільну навігацію на чотири сторінки" $ git push -u origin feature-nav remote: Create a new pull request for 'feature-nav': remote: https://git.<домен>/<клас>/<команда>/compare/main...feature-nav Branch 'feature-nav' set up to track remote branch 'feature-nav' from 'origin'.

Gitea сама підказує посилання на створення PR прямо у виводі git push. Ключ -u потрібен лише першого разу. Він прив’язує твою гілку до однойменної на сервері. Далі досить просто git push.

Питання

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

Крок 8

Код-рев’ю: як читати чужий код і писати зауваження

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

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

Три правила корисного коментаря

  1. Про код, а не про людину. «Тут дублюється навігація» — про код. «Ти неуважний» — про людину, і на це немає технічної відповіді.
  2. Назви місце. «Щось не так зі стилями» змушує автора шукати. «У story.html, рядок 12: style.CSS з великими літерами — на Linux це 404» — це готова задача.
  3. Запропонуй, що зробити. Хоча б напрямок: «винести в style.css», «додати alt», «перейменувати файл малими літерами».

І ще одне, дрібне, але дуже дієве: питання замість вироку. «А що станеться, якщо картинка не завантажиться?» лишає автору місце пояснити, чому він так зробив. Часом виявляється, що правий він.

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

Тренажер: три фрагменти, чотири коментарі

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

Питання

Ти рев’юєш PR однокласника. Він зробив ту саму помилку, за яку тобі самому робили зауваження минулого тижня. Ти пишеш: «Ну класика, знову те саме, вчи вже матчастину». Автор мовчки закриває PR і більше нічого не пропонує. Що конкретно ти зробив не так? І як виглядав би коментар, після якого PR був би виправлений?

Крок 9

Конфлікт злиття: це питання, а не аварія

Git зупиняється не тому, що зламався, а тому, що чесно не знає відповіді

Конфлікт виникає в одному-єдиному випадку. Двоє змінили той самий рядок того самого файлу в різних гілках. Різні файли git зливає сам і мовчки. Різні місця одного файлу — теж сам.

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

гілка main · рядок 10 гілка feature-nav · рядок 10 <a href="index.html">Головна</a> <a href="data.html">Дані</a> <a href="index.html">Головна</a> <a href="story.html">Історія</a> той самий рядок → git не обирає сам index.html після git merge feature-nav <<<<<<< HEAD ======= >>>>>>> feature-nav <a href="data.html">Дані</a> <a href="story.html">Історія</a> твоя версія (та гілка, де ти зараз) версія гілки, яку ти вливаєш Розв’язати = стерти три рядки-маркери й лишити той текст, який має бути в підсумку
Маркери — це не пошкодження файлу. Це два варіанти одного місця, покладені поруч, щоб людина обрала. Часто правильна відповідь — «обидва», просто в потрібному порядку.

Порядок дій при конфлікті

розв’язання конфлікту
$ git merge feature-nav Auto-merging index.html CONFLICT (content): Merge conflict in index.html Automatic merge failed; fix conflicts and then commit the result. $ git status Unmerged paths: both modified: index.html # відкриваєш index.html у редакторі, прибираєш маркери, # лишаєш правильний варіант, зберігаєш $ git add index.html $ git commit [main 7c2f0ab] Merge branch 'feature-nav'

Захотілося почати спочатку — це нормально. Команда git merge --abort повертає гілку в той стан, який був до злиття. Нічого не втрачено.

Другий класичний випадок: push rejected

Конфлікт можна зустріти й без жодного merge — просто спробувавши запушити. Виглядає це так:

push відхилено
$ git push ! [rejected] main -> main (fetch first) error: failed to push some refs to 'https://git.<домен>/<клас>/<команда>.git' hint: Updates were rejected because the remote contains work that you do hint: not have locally. Integrate the remote changes before pushing again. $ git pull --rebase $ git push
було: ви обидва почали від коміту B AB D — Оксана вже запушила C — твій коміт, ще локальний git push → ! [rejected] git pull --rebase: твій коміт переставлено на верхівку AB D C′ → git push проходить
rejected означає одне: поки ти працював, хтось запушив у ту саму гілку. Спочатку забери чуже (pull), потім віддавай своє (push).
Чого робити не можна git push --force у спільну гілку стирає чужі коміти з сервера без попередження. На цьому уроці ключ --force не потрібен жодного разу. Якщо здається, що потрібен, — значить, десь раніше пішло не так, і треба покликати вчителя.
Питання

Ти зробив git push, а git відповів ! [rejected] main -> main (fetch first). Що сталося і яку команду ти набереш першою?

Питання

У файлі після злиття ти бачиш <<<<<<< HEAD, свій варіант навігації, =======, варіант Оксани, >>>>>>> feature-nav. Обидва варіанти потрібні: у твоєму є посилання на data.html, у неї — на story.html. Як правильно розв’язати цей конфлікт?

Крок 10

Ролі в команді: як не блокувати одне одного

Конфлікти в git — це наслідок. Причина майже завжди в тому, що двоє взялися за одне й те саме

Найпростіший спосіб не мати конфліктів — розділити файли. Коли кожен править переважно свої файли, git зливає все сам. Маркери ви побачите хіба що в спільному style.css.

Ролей чотири. Остання в таблиці зветься дизайн / QA. Дві літери QA — це скорочення від англійського quality assurance, «забезпечення якості». Ця людина відкриває кожну сторінку й перевіряє, чи все працює. Робить вона це до того, як робота піде в main.

РольЗа що відповідаєСвої файлиРизик конфлікту
Тимлід беклог, розподіл задач, зливає PR, стежить, щоб main завжди працював README.md, CONTRIB.md низький
Фронтенд каркас сторінок, спільна навігація, підключення стилів index.html, data.html середній: навігація є в усіх файлах
Контент тексти сторінок, перенесення артефактів попередніх тем story.html, media.html низький
Дизайн / QA єдиний style.css, перевірка сторінок, рев’ю чужих PR style.css високий: файл один на всіх

У команді з трьох ролі контент і дизайн/QA об’єднують. Але рев’ю все одно робить не автор коду. Це умова, а не побажання.

Коли задача справді закрита

Домовтеся про це до початку роботи й запишіть у README.md. Такий список умов англійською звуть definition of done. Робоче формулювання для сьогоднішнього уроку:

Пастка «один робить усе» Найшвидший спосіб зробити каркас — віддати його одному фронтендеру. Але git log покаже це на першому ж екрані, і в критеріях стоїть окремий пункт: у кожного учасника мають бути власні коміти. Розділіть сторінки з самого початку.
Крок 11

Практика: каркас командного сайту

Кроки 1—5 робить кожен окремо, кроки 6—11 — за своєю роллю, кроки 12—16 — разом. Галочки зберігаються, сторінку можна закрити.

Підстав своє У командах нижче <клас> заміни на свою організацію (class9a або class9b), <команда> — на номер своєї команди, <домен> — на адресу шкільного сервера, яку дав учитель.
Перший запуск git на новій машині Якщо ти ще не назвався git, твої коміти будуть підписані невідомо ким. Тоді критерій «у кожного учасника є коміти» не зарахується. Ім’я має збігатися з акаунтом у Gitea.
налаштування один раз
$ git config --global user.name "ТВІЙ-ЛОГІН" $ git config --global user.email "ТВІЙ-ЛОГІН@school.local" $ git config --global init.defaultBranch main
Крок 12

Автоперевірка

Чекер читає репозиторій і Gitea API. Він бачить, хто скільки закомітив і хто кого рев’ював — це не приховати. Спроби не обмежені.

Демонстраційний режим: результат згенеровано для показу. На сервері ця кнопка викликає POST /api/check, який запускає check 14 для репозиторію команди.

Що вчитель дивиться очно

Крок 13

Шкала виконання

Це те, що бачить учитель, коли виставляє оцінку.

СкладникВагаРезультат
Виконано
0%
Рекомендований бал за 12-бальною

П’ять речень, які варто запам’ятати

Де найчастіше помиляються

Домашнє завдання

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

Не «тут погано», а, наприклад: «У media.html, рядок 18, посилання href="Style.css" з великої літери. На Linux це інший файл — сторінка відкриється без стилів. Треба style.css».

Джерела

Звідки взяті правила й формулювання

Тексти помилок git на цій сторінці — справжні, зі стандартного виводу. Перевіряти дозволено й корисно.

Повний список із поясненнями, що звідки взято, — у файлі urok-14-джерела.md поруч із цією сторінкою.