Жизненный цикл Snapshot-зависимостей и их роль в разработке
Жизненный цикл Snapshot-зависимостей и их роль в разработке
Представьте ситуацию: вы исправили баг в общей библиотеке (назовем её commons), запушили свою ветку и задеплоили её в удаленный репозиторий. Система сборки выдала вам тестовую версию — aeqs-14-SNAPSHOT. Теперь вам нужно подключить эту библиотеку к тестовому фреймворку, где вы тоже работаете в отдельной ветке. И тут выясняется, что ваш коллега-автотестировщик только что влил свои изменения в master тестового фреймворка.
Голова идет кругом. Что делать сначала? Тянуть изменения из master? Или сначала прописать новый aeqs-14-SNAPSHOT в конфигурации? Чтобы выстроить правильный алгоритм действий, нам нужно на шаг отступить и разобраться: а что вообще представляет собой этот таинственный суффикс -SNAPSHOT и по каким правилам он живет.
Два мира: Release и Snapshot
В мире разработки (особенно в экосистемах Java, Android, и других, использующих Maven или Gradle) любая зависимость имеет версию. Фундаментально все версии делятся на два типа.
Release (Релиз) — это версия, высеченная в камне. Если библиотека получила версию 1.0.0, её код больше никогда не изменится. Если вы скачали 1.0.0 сегодня, а ваш коллега скачает её через год — вы получите абсолютно идентичный набор байтов. Это дает стабильность: ваш код не сломается внезапно из-за того, что кто-то втихую переписал зависимость.
Snapshot (Снэпшот) — это черновик, версия в процессе активной разработки. Суффикс -SNAPSHOT (например, 1.0.0-SNAPSHOT или ваш aeqs-14-SNAPSHOT) говорит системе сборки: «Эта версия еще не готова, она может меняться каждый час».
Релиз можно сравнить с изданной печатной книгой: текст в ней уже не поменять. Snapshot — это ссылка на Google Документ: вы открываете его каждый день и видите новые правки, хотя ссылка (имя версии) остается прежней.
Зачем нужны Snapshots?
Вернемся к вашему проекту. Вы работаете над commons и test-framework одновременно.
Если бы Snapshots не существовало, вам бы пришлось для каждой мелкой правки в commons выпускать полноценный релиз: 1.0.1, 1.0.2, 1.0.3... Репозиторий быстро бы засорился тысячами промежуточных сборок, которые никому не нужны в финальном продукте.
Snapshot решает эту проблему элегантно. Жизненный цикл вашей зависимости aeqs-14-SNAPSHOT выглядит так:
- Разработка: Вы пишете код в своей fix-ветке проекта
commons. - Публикация (Deploy): Вы отправляете сборку в удаленный репозиторий (например, Nexus или Artifactory). Система сохраняет ваш артефакт под именем
aeqs-14-SNAPSHOT. Под капотом она прикрепляет к нему временную метку (timestamp), чтобы отличать сборки друг от друга, но для вас имя остается прежним. - Потребление: Вы идете в проект
test-frameworkи указываете в конфигурации: «Мне нуженaeqs-14-SNAPSHOT». Maven или Gradle идут в удаленный репозиторий, видят, что это Snapshot, и скачивают самую свежую сборку с этим именем. - Итерация: Вы нашли ошибку в
commons. Вы снова правите код и снова деплоитеaeqs-14-SNAPSHOT. Когда вы запустите сборкуtest-framework, система увидит, что в удаленном хранилище появилась более новая версияaeqs-14-SNAPSHOT, и автоматически подтянет её. - Стабилизация: Когда тестирование завершено и все баги исправлены, код сливается в главную ветку, и выпускается релиз (уже без суффикса
-SNAPSHOT).
Как Snapshot диктует правила работы с ветками
Теперь, понимая природу Snapshot, давайте посмотрим на вашу исходную задачу.
У вас есть aeqs-14-SNAPSHOT, который содержит критически важное исправление. Вы находитесь в своей fix-ветке проекта test-framework. И тут master ветка фреймворка обновляется коллегой.
Snapshot — это нестабильная, тестируемая сущность. Если вы прямо сейчас пропишете aeqs-14-SNAPSHOT в свою ветку, не подтянув изменения из master, вы будете тестировать свою новую зависимость на устаревшем коде фреймворка.
Может случиться так, что с вашим старым кодом Snapshot работает отлично, но изменения вашего коллеги в master несовместимы с вашей новой логикой в commons. Если вы сначала настроите зависимость, протестируете, а потом попытаетесь влить в себя master — вы рискуете получить конфликты или сломанные тесты в самом конце работы, когда уже считали задачу выполненной.
Поэтому золотое правило интеграции зависимостей звучит так: сначала актуализируй фундамент, затем добавляй новые кирпичи.
В следующей главе мы подробно разберем, как именно нужно синхронизировать ветки, в какой последовательности выполнять команды git pull и git merge, чтобы безопасно интегрировать ваш aeqs-14-SNAPSHOT в проект, не потеряв ни свои, ни чужие изменения.