# Релізи на GitHub і версії: теги, SemVer, changelog

> Що таке тег Git, як читати номер версії на кшталт v1.4.1 (SemVer простими словами), як працюють релізи на GitHub і згенеровані release notes, чим вони відрізняються від changelog, як перевірити, чи є виправлення у версії, і чому «змерджено», «випущено» і «доступно всім» можуть бути трьома різними моментами.

- Курс: [Git і GitHub для продактів](https://productovi.com/uk/courses/git-for-product.md)
- Модуль: Командні воркфлоу
- Урок 12/15, ~42 хв
- Джерело: https://productovi.com/uk/courses/git-for-product/releases-and-versions

## «У якій версії виправлення?»

**Alex Tutor:** Знову в продуктовій команді Котокорму, і підтримка має прохання щодо виправлення кнопки оформлення.

**Sofia:** Підтримка хоче писати клієнтам «виправлено у версії така-то», як у нотатках до оновлень застосунків. Яка версія була в #134?

**Daniel:** Чесна відповідь: жодної. Глянь на сторінку `Tags` («теги»). Там чотири старі теги, від `v1.0.0` до `v1.3.0`, я ставив їх вручну для великих запусків. Останній стоїть на наборі ласощів.

**Alex Tutor:** **Тег** це постійна назва одного коміту. Гілка рухається вперед із кожним новим комітом, а тег лишається саме там, де його поставили. Тому версії це теги.

```text
Граф комітів, від найстарішого: main і її єдиний свіжий тег
1. коміт 8be2f70 у main "Add cat treats bundle", тег v1.3.0
2. коміт 6f2c8a1 у main "Raise free-delivery threshold to 1000 UAH (#133)"
3. коміт a7d93e4 у main "Rewrite delivery page copy (#132)"
4. коміт d51c7e8 у main "Fix checkout button after cart edits (#134)" (виділено)
5. коміт 3b8e1f6 у main "Add autumn sale banner (#136)"
6. коміт 9c4a2d7 у main "Add loyalty points behind a flag (#155)"
```

*v1.3.0 позначає 8be2f70. Усе, що змерджили після нього, зокрема #134, уже на сайті, але не входить у жодну версію.*

**Sofia:** Тобто тег це як закладка в історії, а `main` пішла від неї на п'ять комітів уперед.

**Daniel:** Так. Технічно тег можна видалити й створити знову, але опублікований тег ніколи не переносять. Люди й інструменти покладаються на те, що `v1.3.0` завжди означає одне й те саме.

![Помаранчева закладка-стрічка міцно прикріплена до однієї сторінки блокнота, а олівець дописує нові сторінки в кінці.](https://productovi.com/courses/git-for-product/inline/releases-and-versions-illustration-2.webp)

*Тег лишається на своєму коміті; опублікований тег ніколи не переносять.*

**Alex Tutor:** Тож відсьогодні команда щочетверга робить реліз: поточна `main`, яка вже на сайті, отримує номер версії й нотатки. Термінові виправлення отримують власну версію одразу.

> **Вправа:** Підтримка питає: «Виправлення кнопки, #134, вийшло у v1.3.0?» Яка правильна відповідь у четвер зранку?

**Alex Tutor:** Daniel сказав, що опублікований тег ніколи не переставляють. Перевірмо це.

> **Вправа:** `v1.3.0` опублікували кілька місяців тому на коміті `8be2f70`. Щоб полегшити життя підтримці, Daniel має переставити тег `v1.3.0` на найновіший коміт `main`, щоб він містив виправлення кнопки #134.

## Як читати номер версії

**Sofia:** Чому `v1.3.0`, а не просто «версія 13»?

**Alex Tutor:** Це **семантичне версіонування**, SemVer: MAJOR.MINOR.PATCH. Кожне число каже, яка зміна відбулася. PATCH зростає для виправлень, MINOR для нових можливостей, які нічого не ламають, MAJOR для змін, що ламають щось, на що люди покладаються.

**Alex Tutor:** Коли число зростає, усі праворуч від нього обнуляються. Після `1.3.0` виправлення дає `1.3.1`, нова можливість `1.4.0`, несумісна зміна `2.0.0`. Більше прикладів є в нашому дописі про [семантичне версіонування](/uk/blog/semantic-versioning-explained).

![У MAJOR.MINOR.PATCH після 1.3.0 виправлення дає 1.3.1, нова можливість, що нічого не ламає, — 1.4.0, а несумісна зміна — 2.0.0.](https://productovi.com/courses/git-for-product/diagrams/m4-l3-semver-uk.png)

**Daniel:** Правила на semver.org написано для програм, від яких залежать інші програми. Для сайту ми вирішили самі: MAJOR, якщо перестають працювати старі посилання, збережені кошики чи інтеграції з партнерами. Сподіваємося, що не знадобиться ніколи.

**Sofia:** А `v` на початку?

**Daniel:** Просто поширена звичка для назв тегів. Сама версія це `1.3.0`. Іноді ще побачиш `2.0.0-beta.1`: це пре-реліз, тестова версія, яка передує справжній `2.0.0`.

> **Вправа:** Котокорм використовує семантичне версіонування: PATCH для виправлень, MINOR для нових фіч, що нічого не ламають, MAJOR лише тоді, коли перестають працювати старі посилання, збережені кошики чи інтеграції партнерів. Останній реліз `v1.4.0`. Зістав кожен наступний реліз із версією, яку він має отримати.

**Sofia:** Одну пастку я вже бачу: `1.4.10` старша за `1.4.9`? За абеткою так і було б.

**Alex Tutor:** Кожна частина це ціле число, і порівнюють їх зліва направо. Десять більше за дев'ять, тож `1.4.10` новіша. А пре-реліз старший за свій реліз: `1.5.0-beta.1` іде перед `1.5.0`.

**Daniel:** До речі, на сторінці тегів GitHub не завжди сортує їх саме так. Довіряй числам, а не порядку в списку.

**Sofia:** Числа, а не абетка. Зрозуміло.

> **Вправа:** Розстав ці версії від найстарішої до найновішої.

## Публікуємо реліз на GitHub: тег v1.4.0

**Alex Tutor:** **Реліз на GitHub** (GitHub release) це сторінка, побудована на тезі Git: номер версії, нотатки до релізу для людей і файли для завантаження. Тег позначає точний коміт, а реліз пояснює, що змінилося від попереднього. Усі релізи лежать у розділі `Releases` репозиторію.

**Alex Tutor:** Четвер, після обіду. Від `v1.3.0` додалися дві нові можливості, банер розпродажу й прихована основа для балів лояльності, тож це MINOR-реліз: `v1.4.0`. Daniel відкриває `Releases` («релізи») зі сторінки репозиторію.

**Daniel:** Станом на 2026 рік: `Draft a new release` («створити чернетку релізу»), вводжу `v1.4.0` як новий тег, ціль `main`. GitHub створить тег під час публікації. Попередній тег `v1.3.0`, а тоді чарівна кнопка: `Generate release notes` («згенерувати нотатки до релізу»).

> **Що згенерувала кнопка Generate release notes**
>
> ```markdown
> ## What's Changed
> * Raise free-delivery threshold to 1000 UAH by @catchow-daniel in https://github.com/catchow/website/pull/133
> * Rewrite delivery page copy by @catchow-emma in https://github.com/catchow/website/pull/132
> * Fix checkout button after cart edits by @catchow-daniel in https://github.com/catchow/website/pull/134
> * Add autumn sale banner by @catchow-emma in https://github.com/catchow/website/pull/136
> * Add loyalty points behind a flag by @catchow-daniel in https://github.com/catchow/website/pull/155
>
> **Full Changelog**: https://github.com/catchow/website/compare/v1.3.0...v1.4.0
> ```
> GitHub генерує нотатки англійською: «What's Changed» (що змінилося) і по рядку на кожен змерджений pull request від попереднього тегу, з автором і посиланням. «Full Changelog» веде на порівняння двох тегів.

**Sofia:** Кожен змерджений pull request від `v1.3.0`, з назвою й автором. Тож добрі назви окупаються двічі.

**Alex Tutor:** Під текстом є місце для файлів, **assets** («ресурси»). GitHub завжди сам додає вихідний код архівами zip і tar.gz; команди застосунків прикладають зібраний застосунок. Нам більше нічого не треба.

**Daniel:** Далі два прапорці. `Set as a pre-release` («позначити як пре-реліз») для тестових версій; сьогодні ні. `Set as the latest release` («позначити як останній реліз»): так. `Publish release`, і сторінка репозиторію показує `v1.4.0` із зеленою позначкою `Latest`.

```text
Два найновіші теги в catchow/website, четвер увечері
- [Tag] v1.4.0: Latest · на 9c4a2d7 · нотатки від Daniel і Sofia
- [Tag] v1.3.0: на 8be2f70 · без сторінки релізу, лише тег
```

> **Вправа:** У четвер Daniel опублікував реліз Котокорму `v1.4.0`: новий тег на `9c4a2d7`, найновішому коміті `main`, із нотатками, згенерованими від попереднього тегу `v1.3.0` (на `8be2f70`), з позначкою `Latest`. Котокорм викладає кожен мердж у `main` за кілька хвилин. Які твердження правильні? Познач усе, що підходить.

## Release notes і changelog: нотатки для людей

**Sofia:** Підтримка не зрозуміє «Add loyalty points behind a flag». І їм точно не можна поки що розповідати клієнтам про бали лояльності.

**Alex Tutor:** У цьому різниця між списком pull requests і **changelog**: записом змін у кожній версії, написаним для тих, хто цим користується. Добрі release notes це такий запис для однієї версії. Згенерований список це сировина, а не готовий текст.

![Розробник передає довгий технічний сувій колезі, а та перетворює його на коротку картку з простими малюнками для усміхненої працівниці підтримки.](https://productovi.com/courses/git-for-product/inline/releases-and-versions-illustration-3.webp)

**Daniel:** Деякі команди ведуть файл `CHANGELOG.md` із розділами на кшталт Added, Changed, Fixed. Нашим changelog будуть сторінки релізів. А ще я додам невеликий конфіг, щоб генератор групував pull requests за мітками: `bug` у розділ «Fixes».

**Alex Tutor:** Тож над згенерованим списком з'являється коротка частина «Для клієнтів і підтримки» простими словами, а сам список лишається нижче для інженерів.

**Sofia:** Що помітять клієнти, що має казати підтримка, і ні слова про приховану роботу.

> **Вправа:** GitHub згенерував для `v1.4.0` такий список:
>
> ```markdown
> ## What's Changed
> * Raise free-delivery threshold to 1000 UAH by @catchow-daniel in #133
> * Rewrite delivery page copy by @catchow-emma in #132
> * Fix checkout button after cart edits by @catchow-daniel in #134
> * Add autumn sale banner by @catchow-emma in #136
> * Add loyalty points behind a flag by @catchow-daniel in #155
> ```
>
> Раніше поріг безкоштовної доставки був 800 грн. #155 схований за флагом `loyalty-points`, який вимкнено. Напиши частину нотаток «Для клієнтів і підтримки» (3–5 коротких рядків). Бали лояльності анонсувати поки не можна.

**Alex Tutor:** Коротка перевірка тону цих рядків.

> **Вправа:** Який рядок має бути в частині «Для клієнтів і підтримки» нотаток до `v1.4.0`?

## Змерджено, випущено, доступно всім

**Sofia:** Стривай. #134 з'явився на сайті минулої середи, а «випустили» його сьогодні. Тобто в Котокормі реліз настає тоді, коли клієнти вже мають зміну?

**Alex Tutor:** Так. У нас «змерджено» означає «на сайті за кілька хвилин», а реліз це названий знімок, про який людям зручно говорити. Три слова, але в Котокормі два з них зазвичай стаються одночасно.

![Посилка з кормом проходить крізь троє дверей поспіль: двері майстерні, двері зі стрічкою й відчинені двері крамниці з покупцями.](https://productovi.com/courses/git-for-product/inline/releases-and-versions-illustration-4.webp)

*Перш ніж відповідати, чи це вже на сайті, спитай себе: змерджено, випущено чи видно покупцям?*

**Daniel:** На моїй старій роботі всі три були далеко одне від одного. Змерджено в `develop`, випущено за кілька тижнів, потім перевірка в магазині, і навіть після схвалення магазини можуть поширювати версію поступово, на дедалі більшу частку користувачів.

**Alex Tutor:** А флаги відокремлюють «випущено» від «видно» навіть у нас. #155 входить у `v1.4.0`, але жоден клієнт його не бачить.

**Sofia:** Тож коли мене питають «це вже працює?», я спершу питаю себе: змерджено, випущено чи видно клієнтам?

> **Вправа:** Зістав кожну ситуацію з тим, що клієнти мають насправді.

## П'ятниця зранку: хотфікс

**Sofia:** Підтримка щойно переслала два повідомлення. Клієнти бачать у меню особистого кабінету нове посилання «Бали лояльності», і воно відкриває порожню сторінку.

**Daniel:** Моя помилка. У #155 розділ лояльності перевіряє флаг, а посилання в меню ні. Його видно з вівторка. Виправлення на два рядки.

**Alex Tutor:** Це **хотфікс**: термінове виправлення того, що клієнти вже мають. У GitHub flow це не окремий тип гілки, а просто малий pull request у `main`, який іде поза чергою.

**Daniel:** Після `v1.4.0` нічого більше не мерджили, тож після виправлення `main` це `v1.4.0` плюс одне виправлення. Якби туди проскочила нова можливість, чесно було б назвати це `v1.5.0`.

**Alex Tutor:** Сплануй це, поки Daniel не почав: шлях до сайту, версію, нотатки і що підтримка скаже двом клієнтам.

> **Вправа:** Сплануй хотфікс для посилання на бали лояльності в меню і напиши нотатки до його релізу.

**Daniel:** Готово до 11:30. #158 «Hide loyalty menu link when flag is off», Oscar схвалив, preview подивилися і ти, і Oscar, змерджено через squash як `e5f81a3`, викладено. `v1.4.1` опубліковано, і тепер позначка `Latest` на ньому.

## Чи є #134 у v1.4.1?

**Sofia:** Закладаюся, наступне питання підтримки: чи є виправлення кнопки і в `v1.4.1`? У його нотатках його немає.

```text
Граф комітів, від найстарішого: main із двома новими тегами
1. коміт 8be2f70 у main "Add cat treats bundle", тег v1.3.0
2. коміт 6f2c8a1 у main "Raise free-delivery threshold to 1000 UAH (#133)"
3. коміт a7d93e4 у main "Rewrite delivery page copy (#132)"
4. коміт d51c7e8 у main "Fix checkout button after cart edits (#134)" (виділено)
5. коміт 3b8e1f6 у main "Add autumn sale banner (#136)"
6. коміт 9c4a2d7 у main "Add loyalty points behind a flag (#155)", тег v1.4.0
7. гілка fix/loyalty-menu-link починається від коміту 9c4a2d7
8. коміт 0d7b3c9 у fix/loyalty-menu-link "Check flag before showing menu link"
9. коміт e5f81a3: fix/loyalty-menu-link змерджено в main через squash "Hide loyalty menu link when flag is off (#158)", тег v1.4.1
```

*Кожен тег позначає один коміт. v1.4.1 стоїть далі на тій самій лінії, тож містить усе з v1.4.0 плюс e5f81a3.*

**Alex Tutor:** Нотатки до релізу перелічують лише нове від попередньої версії. Але версія містить усе, що було до неї на тій самій лінії. `v1.4.1` пізніша за `v1.4.0`, а `v1.4.0` містить `d51c7e8`.

**Daniel:** Довести це на GitHub можна двома способами. Порівняння `v1.4.0...v1.4.1` показує, що саме додалося між тегами: один коміт. А станом на 2026 рік сторінка коміту перелічує теги, які його містять.

**Sofia:** Тож на `d51c7e8` я побачу і `v1.4.0`, і `v1.4.1`, але не `v1.3.0`.

**Alex Tutor:** Саме так. Цю відповідь підтримка може пересилати: «виправлено у 1.4.0 і в кожній версії після неї».

> **Вправа:** Daniel відкриває порівняння `v1.4.0...v1.4.1`. Які pull requests воно покаже?

**Sofia:** А якщо в мене є лише сторінки релізів?

**Alex Tutor:** Тоді читай їх по порядку. Знайди першу версію, у нотатках якої згадано виправлення, і пам'ятай, що кожна наступна версія його зберігає, хіба що пізніші нотатки кажуть, що його відкотили.

**Daniel:** Це «хіба що» важливе. Згадай мій березневий revert: пізніша версія може щось і забрати.

**Sofia:** Отже, перша поява плюс жодного revert після неї. Добре.

> **Вправа:** Підтримка питає: «Чи є виправлення кнопки #134 у `v1.4.1`?» Які способи перевірки дають надійну відповідь? Познач усе, що підходить.

**Alex Tutor:** Це модуль 4: GitHub flow у нас, git flow там, де реліз це подія, і версії, завдяки яким на питання «це вже працює, і в якій версії?» є відповідь в один рядок.

**Sofia:** А тепер балам лояльності потрібне місце, де вся команда бачить, що лишилося до запуску.

**Daniel:** Issues, мітки, майлстоун і дошка проєкту. Це наступний модуль, і там ти власноруч зробиш свою першу зміну.

- Попередній урок: [Git flow: гілки develop, release і hotfix](https://productovi.com/uk/courses/git-for-product/git-flow.md)
- Наступний урок: [Баг-репорт і GitHub issues: шаблони, мітки й майлстоуни](https://productovi.com/uk/courses/git-for-product/issues-labels-milestones.md)

---
Productovi Learning. Безкоштовно, читати можна без реєстрації.
