Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке Git теги і коли їх використовувати?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Git теги** - це незмінні посилання на конкретні коміти, якими позначають версії релізів. Annotated теги (`git tag -a v1.0.0 -m "msg"`) зберігають метадані: автора і дату; lightweight теги - просто вказівник на коміт. **Головне:** теги не рухаються, на відміну від гілок.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Git теги** - це незмінні посилання на конкретні коміти, якими позначають точки релізу на кшталт v1.0.0. ## Теорія ### TL;DR - Тег - це стікер на конкретному коміті: він залишається там назавжди, на відміну від гілки, яка рухається вперед з кожним новим комітом - Два типи: lightweight (просто вказівник) і annotated (повний об'єкт з повідомленням, автором, датою) - Annotated теги для релізів; lightweight для швидких локальних міток - Теги не пушаться автоматично - потрібно робити це явно ### Швидкий приклад ```bash # Lightweight тег (просто вказівник) git tag v1.0 # Annotated тег (об'єкт з метаданими) git tag -a v1.1.0 -m "Стабільний реліз v1.1.0" # Список тегів git tag # v1.0 # v1.1.0 # Запушити конкретний тег git push origin v1.1.0 ``` Після `git tag -a` Git створює окремий об'єкт тегу: хто тегував, коли і з яким повідомленням. Lightweight теги пропускають все це і просто вказують на SHA коміту. ### Головна різниця: теги проти гілок Вказівник гілки рухається вперед з кожним комітом. HEAD на `main` сьогодні - це не той самий коміт що й HEAD на `main` минулого тижня. Тег ніколи не рухається. `v1.0.0` вказуватиме на той самий коміт через рік. Саме ця незмінність робить теги корисними для релізів - завжди можна повернутись до точно того що пішло в продакшен. ### Коли використовувати теги - Позначення релізів: annotated теги для версій типу `v2.0.0` з повідомленням про зміни - Хотфікси на старих версіях: спочатку тегуй базовий коміт, потім створюй гілку (`git checkout -b hotfix v1.0.0`) - Тригери в CI/CD: пуш тегу запускає деплой на продакшен - Локальні закладки: lightweight теги підходять для "треба сюди повернутись" під час розробки Для роботи в процесі - тільки гілки, не теги. ### Як це працює всередині Git зберігає теги у `.git/refs/tags/`. Lightweight тег - це просто файл з SHA коміту. Annotated тег створює окремий об'єкт у базі Git зі своїм SHA, який вже вказує на коміт. Коли виконуєш `git checkout v1.0.0`, Git переходить у стан detached HEAD - HEAD вказує безпосередньо на хеш коміту, а не на ім'я гілки. ### Типові помилки **Забувають запушити теги.** `git push` не чіпає теги. Команда витягнула зміни і бачить порожній список тегів. ```bash # Неправильно git tag v1.0.0 git push # тег залишається локальним # Правильно git push origin v1.0.0 # або одразу всі git push --tags ``` **Коміти у стані detached HEAD після checkout тегу.** Якщо зробити checkout тегу і почати комітити, ці коміти не належать жодній гілці. Перейдеш на іншу гілку - вони пропадуть. ```bash # Неправильно git checkout v1.0.0 # ... правки, коміт ... git checkout main # коміти тепер "висять" без гілки # Правильно git checkout -b hotfix-v1.0.0 v1.0.0 # тепер ти на гілці, коміти в безпеці ``` **Lightweight теги для релізів.** Немає повідомлення, немає автора, немає дати. `git show v1.0` просто показує сирий коміт. Annotated теги дають контекст для аудиту. Команди які використовують lightweight теги для релізів зазвичай жалкують про це через пів року - коли вже не зрозуміло хто і навіщо це тегував. **Видалення опублікованого тегу.** Локальне видалення (`git tag -d v1.0.0`) не прибирає тег з remote. Видалення з remote (`git push origin :refs/tags/v1.0.0`) ламає CI-пайплайни і всіх хто прибиндився до цього тегу. Координуй з командою перед видаленням будь-якого опублікованого тегу. ### Де зустрічається в реальних проектах - npm: `npm version patch` автоматично створює коміт і тег `v1.2.3` за один крок - React на GitHub: теги типу `v18.2.0` позначають точний коміт перед публікацією в npm - Ядро Linux: теги `v6.1`, `v6.2` маркують merge window для збірок дистрибутивів - Docker Hub: пуш тегу може тригерити збірку Docker-образу автоматично - `semantic-release`: читає теги щоб обчислити наступну версію без ручного втручання ### Питання на співбесіді **Q:** Яка різниця між lightweight і annotated тегом? **A:** Lightweight тег - файл з SHA коміту. Annotated тег - окремий об'єкт Git з ім'ям автора, email, датою і повідомленням. Для будь-чого спільного або пов'язаного з релізами - тільки `git tag -a`. **Q:** Як запушити всі теги одразу? **A:** `git push --tags` пушить усі локальні теги. `git push origin --follow-tags` (Git 2.16+) пушить тільки annotated теги досяжні з поточної гілки - зазвичай кращий варіант для більшості воркфлоу. **Q:** Що таке detached HEAD при checkout тегу? **A:** HEAD вказує безпосередньо на хеш коміту замість імені гілки. Будь-які нові коміти не потраплять у жодну гілку і можуть бути втрачені при переключенні. **Q:** Чи можна перенести тег на інший коміт? **A:** Локально: видали (`git tag -d v1.0.0`) і створи заново. На remote: спочатку видали (`git push origin :refs/tags/v1.0.0`), потім запуши знову. На спільних репозиторіях це болісна процедура - уникай з вже опублікованими тегами. **Q:** У монорепозиторії з десятками пакетів як тегувати окремий пакет без тегування всього репо? **A:** Для цього є Changesets або Lerna. Вони створюють теги у форматі `@org/package@v1.0.0` і запускають тегування в CI, щоб не робити це вручну для кожного пакету окремо. ## Приклади ### Базовий: створення та перевірка annotated тегу ```bash git checkout main git pull origin main # Annotated тег для релізу git tag -a v2.0.0 -m "Мажорне оновлення: нова система авторизації" # Перевіряємо об'єкт тегу git show v2.0.0 # tag v2.0.0 # Tagger: Jane Dev <jane@example.com> # Date: Mon Oct 14 11:30:00 2024 # Мажорне оновлення: нова система авторизації # # commit abc1234... # Пушимо тег git push origin v2.0.0 ``` Вивід `git show` містить метадані автора тегу - їх немає у lightweight тегів. Це важливо коли розбираєш що саме пішло в продакшен і хто це підтвердив. ### Середній: тег як тригер деплою в Node.js проекті ```bash # Типовий Express/Node воркфлоу git checkout main git pull origin main # спочатку запускаємо тести # npm version створює коміт і тег автоматично npm version 4.18.2 -m "Release Express 4.18.2" # створює тег v4.18.2 # Пушимо коміт і тег разом git push origin main --follow-tags # У конфігурації CI (GitHub Actions): # on: # push: # tags: # - 'v*' # Деплой-джоб запускається тільки при пуші тегу версії ``` Флаг `--follow-tags` пушить і коміт гілки, і досяжні annotated теги за один раз. Не треба окремо пам'ятати про тег - він іде разом з кодом.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.