Модуль I · Хмарні сервіси й документи · тема 8, урок 1 з 2 · 120 хвилин
Далі на сторінці трапляться слова «репозиторій», «коміт», «гілка», «pull request» і «конфлікт злиття». Поки вони нічого не означають. Розберемо їх по черзі.
Тринадцять уроків ти працював сам: свій акаунт, своя тека ~/www/,
свій FTP-клієнт. Сьогодні все змінюється. У вас одна тека на трьох-чотирьох,
і кожен правитиме в ній файли одночасно з рештою.
Мета. Працювати в спільній теці так, щоб чужі зміни не затирали твої. Для цього є звичний порядок: гілка, коміт, pull request, рев’ю, злиття. А ще ви зверстаєте каркас командного сайту. Це чотири сторінки зі спільною навігацією й одним файлом стилів.
git push — і сервер сам розкладає файли й оновлює
https://team<N>.<домен>/. FTP лишається тільки
для особистого дзеркала в ~/www/team/.Уяви спільну шафу для файлів команди, ключ від якої є в кожного. У класі така шафа справді є. Це Gitea — сервер git на нашому власному VPS.
Він робить те саме, що GitHub: сторінка проєкту, гілки, заявки на злиття, коментарі до коду. Різниця одна — він наш. Твої файли не виходять за межі шкільного сервера. І акаунт той самий, що й для SSH.
| Клас | Організація в Gitea | Твій репозиторій | Сайт команди |
|---|---|---|---|
| 9-А | class9a | class9a/team-N | team<N>.<домен> |
| 9-Б | class9b | class9b/team-N | team<N>.<домен> |
| Етап | Хв | Що робимо |
|---|---|---|
| Формування команд | 15 | Ролі, спільний список задач, ознаки готовності |
| Теорія: git і три місця файлу | 20 | Граф комітів, add/commit/push |
| Перший коміт і PR | 20 | Клон, гілка, коміт, 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; у кожного учасника — свої коміти під своїм
акаунтом. Сайт відкривається за адресою команди.Три задачі, які він розв’язує, і чому без нього командний проєкт розвалюється на другий день
Уяви теку командного проєкту без git. У ній лежить це:
Це не жарт. Так виглядає майже кожен спільний проєкт без системи
контролю версій. І головне питання тут навіть не «де потрібний файл».
Питання інше: що змінилося між фінал і фінал_2
і хто це зробив. Відповіді немає в жодного з учасників.
| Задача | Без git | З git |
|---|---|---|
| Історія змін | копії файлів із датами в назві | git log: хто, коли, що і навіщо — по кожному рядку |
| Відкотитися | «у когось був бекап позавчора?» | будь-який стан проєкту повертається однією командою |
| Двоє в одному файлі | той, хто зберіг другим, затер першого | git зливає обидві зміни; якщо не може — зупиняється й питає |
| Хто автор рядка | ніхто не знає | git blame показує коміт і автора кожного рядка |
Після git clone у тебе на комп’ютері лежить повна історія
проєкту. Не шматок, а вся — від найпершого коміту. Саме тому git звуть
розподіленою системою контролю версій.
Через це git log працює навіть без мережі. А Gitea —
це не «головний git». Це просто спільна точка обміну для всієї команди.
Твоя команда домовилася обмінюватися файлами через спільну теку
в хмарі: хто закінчив — той залив. О 14:20 ти зберіг style.css,
о 14:22 те саме зробила Оксана зі своєї копії. Що станеться з твоїми
змінами і чим тут допоміг би git?
Це найважливіша схема уроку. Половина «незрозумілих» помилок git — це нерозуміння, у якому з трьох місць зараз файл
Коли ти правиш HTML у звичайному редакторі, файл існує в одному місці — на диску. У git місць три, і файл проходить їх по черзі.
Цими п’ятьма командами робиться майже вся щоденна робота. Решту git ти вивчиш тоді, коли реально впрешся в задачу, яку без неї не розв’язати.
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 показує твій
коміт першим рядком. Де застрягла робота?
-mНайдешевша річ, яку можна зробити для команди, — і та, на якій економлять найчастіше
Коміт без повідомлення — це фотографія без підпису. Через тиждень ніхто, включно з автором, не згадає, що там усередині. А шукати доводиться саме тоді, коли щось зламалося. Треба ж зрозуміти, який коміт це зробив.
| Погано | Чому погано | Добре |
|---|---|---|
фікс | що саме зламалося? де? | Виправити шлях до style.css на story.html |
ще раз | нічого не каже взагалі | Додати посилання на data.html у навігацію |
зміни | коміт завжди про зміни | Прибрати дубль CSS із чотирьох сторінок |
. | класика ліні | Зверстати підвал з іменами команди |
Перший рядок повідомлення — це заголовок. Правила, які склалися в git за двадцять років і які підтримує кожен інструмент:
git log --oneline
і в списку комітів Gitea;Наказова форма — не примха. Її обрали тому, що git сам пише повідомлення
в такому ж стилі: Merge branch 'feature-nav',
Revert "Додати підвал". Коміт відповідає на питання
«що зробить проєкт, якщо я його застосую».
Через три тижні сайт команди перестав показувати стилі. Ти відкриваєш
git log --oneline і бачиш двадцять комітів. Вісім із них
називаються «фікс», п’ять — «ще раз», решта осмислені. Скільки часу
забере пошук винного коміту? І що треба було робити раніше,
щоб пошук зайняв хвилину?
Гілка — це не копія теки. Це рухома закладка на коміті
У репозиторії є головна гілка — main. Саме з неї сервер
бере файли й публікує сайт команди. Робить він це сам, щойно в гілці
з’являється новий коміт. Такий автоматичний сигнал зветься webhook.
Звідси просте правило: у main має лежати тільки те,
що працює. Недороблена навігація в main — це зламаний
сайт для всього класу.
Тому кожен робить свою роботу в окремій гілці. Гілка відгалужується
від main і живе кілька годин або днів. Коли робота готова
й перевірена, вона зливається назад.
feature-nav відгалузилася від main після
коміту «стилі», прожила два коміти й повернулася злиттям. Поки вона жила,
у main устигли зайти ще два чужі коміти — і це нормально.Стара форма тієї самої команди — git checkout -b feature-nav.
Вона працює скрізь і досі трапляється в інструкціях. Але
git switch зрозуміліший: він робить одну річ, а не сім.
feature-nav,
fix-css-path, page-data;feature-nav,
а не denys (Денис завтра робитиме іншу задачу);main і останній коміт твоєї гілки. Git бере обидва набори змін
і складає їх в один результат. Якщо ви правили різні файли або різні рядки —
він робить це сам, мовчки. Якщо той самий рядок — зупиняється і питає тебе.Твоя команда домовилася: усі працюємо в main, «щоб не плутатися
з гілками». Через двадцять хвилин сайт команди відкривається з поламаною
версткою. Виправити її не встигають: кожен новий push ламає щось іще.
Назви дві різні проблеми, які створила ця домовленість.
Головний інтерактив уроку. Тут можна зламати все — і побачити, як воно лагодиться
Пісочниця — це тренажер, який поводиться як справжній git, але не чіпає жодного справжнього файла. Натискай тут будь-що: репозиторій команди від цього не зміниться.
Нижче — справжня модель git у мініатюрі. У ній один файл
index.html і три рядки, які можна правити. Цикл повний: правка,
add, commit, гілка, злиття. Дерево комітів
малюється саме́.
Як спровокувати конфлікт. Змінити той самий рядок у двох різних гілках і спробувати їх злити. Кнопка «Створити конфлікт» робить це за тебе в чотири кроки — але цікавіше зібрати руками.
index.html у робочій теці гілки main
3a91c7d і його не можна вгадати. У пісочниці
хеші вигадані для наочності, файл один, а рядків для правки три. Уся решта
логіки — справжня: індекс, батьки комітів, пошук спільного предка,
fast-forward, маркери конфлікту.У пісочниці ти створив гілку й зробив у ній коміт. Потім злив її
в main, де відтоді нічого не мінялося.
Git написав Fast-forward
і не створив коміт злиття. Чому в цьому випадку коміт злиття
не потрібен?
Технічно злиття робиться однією командою. PR потрібен, щоб перед злиттям на код подивилася людина
Ти закінчив роботу у своїй гілці. Тепер треба сказати команді: «я зробив
навігацію в гілці feature-nav, візьміть її в main».
Таке прохання пишуть не в чаті, а окремою сторінкою прямо в Gitea.
Ця сторінка зветься pull request. У Gitea і GitHub її скорочують до двох літер — PR.
Заявку видно всій команді. Під нею пишуть коментарі до конкретних рядків. А кнопка «Merge» вмикається тільки тоді, коли хтось підтвердив рев’ю.
Опис читає людина, яка не сиділа поруч, коли ти це робив. Три речення економлять їй десять хвилин:
Gitea сама підказує посилання на створення PR прямо у виводі
git push. Ключ -u потрібен лише першого разу.
Він прив’язує твою гілку до однойменної на сервері. Далі досить
просто git push.
Ти відкрив PR, тимлід залишив три зауваження. Ти їх виправив у себе локально. Що зробити, щоб зауваження закрилися: створити новий PR, перевідкрити цей чи щось третє?
Рев’ю — це не оцінка людини і не змагання. Це остання можливість спіймати помилку до того, як її побачить користувач
Автор коду не бачить власних помилок. Він бачить те, що хотів написати.
Свіжа людина помічає це за тридцять секунд: забутий alt,
шлях із великої літери, чотири копії однієї навігації.
story.html, рядок 12: style.CSS з великими
літерами — на Linux це 404» — це готова задача.style.css», «додати alt», «перейменувати файл
малими літерами».І ще одне, дрібне, але дуже дієве: питання замість вироку. «А що станеться, якщо картинка не завантажиться?» лишає автору місце пояснити, чому він так зробив. Часом виявляється, що правий він.
Нижче — три реальні шматки коду з учнівських проєктів. У кожному є конкретна проблема. Обери коментар, який ти написав би автору, і подивись розбір усіх чотирьох.
Ти рев’юєш PR однокласника. Він зробив ту саму помилку, за яку тобі самому робили зауваження минулого тижня. Ти пишеш: «Ну класика, знову те саме, вчи вже матчастину». Автор мовчки закриває PR і більше нічого не пропонує. Що конкретно ти зробив не так? І як виглядав би коментар, після якого PR був би виправлений?
Git зупиняється не тому, що зламався, а тому, що чесно не знає відповіді
Конфлікт виникає в одному-єдиному випадку. Двоє змінили той самий рядок того самого файлу в різних гілках. Різні файли git зливає сам і мовчки. Різні місця одного файлу — теж сам.
А от чий варіант одного рядка правильний, git вирішити не може. Це питання не технічне, а змістове. Тому він робить єдине розумне — зупиняється. Вписує обидва варіанти прямо у файл, розділяє їх маркерами і чекає людину.
Захотілося почати спочатку — це нормально. Команда
git merge --abort повертає гілку в той стан, який був
до злиття. Нічого не втрачено.
Конфлікт можна зустріти й без жодного merge — просто спробувавши запушити. Виглядає це так:
rejected означає одне: поки ти працював, хтось
запушив у ту саму гілку. Спочатку забери чуже (pull),
потім віддавай своє (push).git push --force у спільну гілку стирає чужі коміти з сервера
без попередження. На цьому уроці ключ --force не потрібен жодного
разу. Якщо здається, що потрібен, — значить, десь раніше пішло не так,
і треба покликати вчителя.Ти зробив git push, а git відповів
! [rejected] main -> main (fetch first).
Що сталося і яку команду ти набереш першою?
У файлі після злиття ти бачиш <<<<<<< HEAD,
свій варіант навігації, =======, варіант Оксани,
>>>>>>> feature-nav. Обидва варіанти потрібні:
у твоєму є посилання на data.html, у неї — на
story.html. Як правильно розв’язати цей конфлікт?
Конфлікти в 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. Робоче формулювання
для сьогоднішнього уроку:
main;CONTRIB.md.git log покаже це на першому ж екрані, і в критеріях
стоїть окремий пункт: у кожного учасника мають бути власні коміти.
Розділіть сторінки з самого початку.Кроки 1—5 робить кожен окремо, кроки 6—11 — за своєю роллю, кроки 12—16 — разом. Галочки зберігаються, сторінку можна закрити.
<клас> заміни на свою організацію
(class9a або class9b), <команда> — на номер
своєї команди, <домен> — на адресу шкільного сервера,
яку дав учитель.Чекер читає репозиторій і Gitea API. Він бачить, хто скільки закомітив і хто кого рев’ював — це не приховати. Спроби не обмежені.
Демонстраційний режим: результат згенеровано для показу. На сервері
ця кнопка викликає POST /api/check, який запускає
check 14 для репозиторію команди.
git log --oneline --graph —
видно гілки, а не рівний стовпчик комітів у main;git status
просто зараз;Це те, що бачить учитель, коли виставляє оцінку.
| Складник | Вага | Результат |
|---|
add) →
репозиторій (commit), і далі на сервер (push);main лежить тільки те, що працює; усе інше — у гілках;--abort
завжди повертає все назад;rejected означає «спочатку забери чуже»: git pull --rebase,
потім git push;main — сайт ламається щопівгодини;git add — закомітили порожнечу і не розуміють, чому
на сайті нічого не змінилося;Довести кількість власних комітів до чотирьох. І залишити щонайменше одне змістовне рев’ю на чужому PR. Змістовне — це таке, де названо проблему, місце й спосіб виправлення.
Не «тут погано», а, наприклад: «У media.html, рядок 18,
посилання href="Style.css" з великої літери. На Linux
це інший файл — сторінка відкриється без стилів. Треба style.css».
Тексти помилок git на цій сторінці — справжні, зі стандартного виводу. Перевіряти дозволено й корисно.
git-merge — стратегія ort,
--abort, поведінка при конфлікті.
git-scm.com/docs/git-mergegit-switch — сучасна заміна
checkout для перемикання гілок.
git-scm.com/docs/git-switchgit-push — чому виникає
[rejected] (fetch first) і чим небезпечний --force.
git-scm.com/docs/git-pushgit-status — що означає кожен розділ виводу.
git-scm.com/docs/git-statusПовний список із поясненнями, що звідки взято, —
у файлі urok-14-джерела.md поруч із цією сторінкою.