Видалити Git тег. Місія неможлива

Так-так, звісно, ви можете зробити git tag -d <tagname> а потім git push --delete origin <tagname>! Але є дуже вискоі шанси що тег воскресне незабаром. Читайте далі, якщо хочете дізнатись чому.

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

Нещодавно ми виявили, що завантаження на сервіс не атомарне. Це означає, що, наприклад, 6 з 8 мов можуть завантажитись на сервер, залишаючи наші переклади неузгодженими.

Ми повинні були якось зробити завантаження атомарними. Ми вирішили використати щось на кшталт Write Ahead Lock (WAL).

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

  • створити тег з спеціальною назвою
  • запустити операцію
  • видалити тег

Якщо щось піде не так під час операції (внутрішня помилка сервера, мережа впаде, тощо), тег не буде видалений. Якщо при наступному запуску ми виявимо що тег існує, відбудуться дії відновлення.

Щоб все було супер надійно, ми вирішили пушити ці теги.

Наступні кілька днів ми почали спостерігати дивну поведінку. Механізм відновлення спрацьовував занадто часто. Але коли ми перевірили логи… на попередньому запуску не було помилок! Тег був належним чином видалений скриптом. Єдиний спосіб для тегу з’явитись знову був якщо хтось із людей перестворив його. І виявляється, так і було! Але чому?

Завантаження на сервіс займає деякий час (декілька хвилин). Під час цього періоду люди можуть отримати тег. А потім із нами грає два факти:

  • дуже мало людей чистять теги. Чесно кажучи, я сам ніколи не чищу теги. Наприклад, SourceTree збирає інтерес до цієї фічі з 2017 року (має бути дуже складна фіча, мабуть).
  • GUI додатки пушать теги за замовчуванням (я перевірив SourceTree і Fork)

Тож я видалив пуш тегів. І щоб бути впевненим, додав --no-tags до git fetch щоб теги не фетчились.

Готово! Готово? Не так швидко! Це Git, крихітко…

Транзакції для вже запушених тегів продовжували жити своїм життям. Теги якось продовжували оживати з remote.

Вся команда fetch виглядала так: git fetch --no-tags -Pp.

-P означає “чистити теги”.

А --no-tags каже “не фетчити нові теги”. Так я думав. У Git інша думка. -P фактично вимикає --no-tags і фетчить всі теги щоб… почистити видалені після цього.

Я видалив -P і тоді нарешті наші транзакції заспокоїлись.

Загалом. Якщо ви чистите теги, пам’ятайте що вони можуть легко оживати. І CLI і особливо GUI клієнти роблять цю проблему дуже ймовірною.