Глава 2: Параллельные реальности — версионирование и ветвление
Новые идеи в этой главе
- Иерархические версии: Вместо простых номеров версий используются иерархические идентификаторы (например,
1.2.feature-x.3
). Это объединяет концепции версии, ветки и черновика в единую мощную структуру. - Двойственность веток: Два типа веток работают вместе: Ветки (например,
main
илиstaging
) определяют, где виден Vibe, в то время как Ревизии в ветках (например,.feature-x.
) внутри версий создают альтернативные линии разработки, которые можно использовать для разработки, наложения конфигураций или расширения системы. - Путь поиска как механизм наложения: Поиск нужной версии управляется путем поиска с приоритетами (например,
['feature-x', 'main']
). Этот список действует как механизм наложения, позволяя разработчикам видеть свою работу в ветке как бы бесшовно наложенной поверх стабильной системы. - URI, знающие о ветках: Схема ссылок
aug:
позволяет перемещаться в этой многоветочной реальности, делая запросы, которые могут быть либо неявными (с учетом пути поиска), либо явными (нацеленными на конкретную ветку). - Контролируемый волновой эффект: Продвижение версии из ветки с критическими (несовместимыми) изменениями может безопасно и автоматически обновлять зависимости для потребителей, которые выбрали соответствующий диапазон совместимости, делая развитие предсказуемым.
Проблема: управление изменениями и параллелизм
Любая развивающаяся система сталкивается с двумя основными задачами: управление изменениями (версионирование) и обеспечение параллельной работы (ветвление). Система решает обе задачи с помощью единой модели, в которой эти две концепции тесно переплетены. В этой главе объясняется механика этих «параллельных реальностей» и показывается, как версии, ветки и система поиска с приоритетами работают вместе, чтобы создать безопасную, гибкую и мощную среду для разработки и экспериментов.
Алиса: «То есть, мы решаем сразу две большие проблемы — как всё меняется со временем и как разные люди могут работать над одним и тем же одновременно?» Боб: «Именно. И вместо того, чтобы рассматривать их как отдельные вопросы, мы создали единый подход, где версионирование и ветвление работают слаженно.» Алиса: «Звучит мощно. А как это работает на практике?» Боб: «Давай разберем все по частям, начиная с того, как мы идентифицируем Vibe в этой системе.»
Часть 1: Анатомия идентификатора — Версии
Идентификатор Vibe состоит из двух компонентов: его path
(текстовый идентификатор, например articles/common/button
) и его version
(иерархический идентификатор). Версия — это не просто число, а богатая, разделенная точками иерархия, которая рассказывает историю развития Vibe. Эта элегантная структура бесшовно сочетает традиционное версионирование с возможностями ветвления и создания черновиков.
В простейшей форме версия может быть одним числом, например 1
или 2
. Но настоящая мощь заключается в её иерархической природе. Например, версия 1.2.feature-x.3
говорит нам, что это третья ревизия ветки feature-x
, которая была создана из версии 1.2.
Идентификатор Vibe — это его `path` и `version`. Версия — это иерархический
идентификатор вроде `1.2.feature-x.3`, который отражает происхождение и состояние Vibe.
Алиса: «То есть, вместо просто 'версия 5', Vibe может быть 'версия 1.4.my-hotfix.2'?» Боб: «Именно. И просто взглянув на эту версию, вы понимаете, что это вторая ревизия ветки 'my-hotfix', которая была ответвлена от публичной версии 1.4 Vibe.»
Часть 2: Анатомия видимости — Ветки и пути поиска
В то время как Версия представляет состояние и историю Vibe, модель ветвления определяет, где и как его можно увидеть. Это работает через две взаимодополняющие концепции: Ветки и Путь поиска.
Ветки: «Где»
Каждая версия Vibe в базе данных связана с одной или несколькими Ветками (например, ["main", "feature/new-billing"]
). Эти ветки действуют как каналы, контролирующие видимость. Vibe виден пользователю или процессу только в том случае, если он опубликован хотя бы в одной из веток, включенных в путь поиска их запроса.
Путь поиска: «Как»
Настоящая мощь системы заключается в Пути поиска. Это упорядоченный список имен веток, который указывает системе поиска, где искать Vibe и в каком порядке приоритета. Типичный путь поиска во время разработки может выглядеть так:
['feature/my-new-idea', 'staging', 'main']
Эта конфигурация создает каскадную систему наложения:
- Сначала искать Vibe, опубликованный в ветке
feature/my-new-idea
. - Если не найден, искать тот, что опубликован в ветке
staging
. - Наконец, вернуться к Vibe, опубликованному в ветке
main
.
Это позволяет разработчику видеть полную, функциональную среду, состоящую из его конкретных изменений, наложенных поверх общей, стабильной системы, без необходимости дублировать каждый Vibe.
Видимость контролируется ветками, которые определяют, где виден Vibe.
Путь поиска (`['feature-x', 'main']`) — это список с приоритетами, который говорит
системе поиска, где и в каком порядке искать. Это создает бесшовное наложение,
показывая работу в ветке поверх стабильной системы.
Алиса: «То есть, если мой путь поиска —
['my-feature', 'main']
, и я запрашиваюcommon/button
, система сначала будет искать версиюcommon/button
, опубликованную в моей ветке?» Боб: «Именно. И если вы её не трогали и там нет опубликованной версии, система вернется к поиску стандартной версии, опубликованной вmain
.» Алиса: «Значит, я получаю свои локальные изменения плюс стабильную основу изmain
, и все это бесшовно.» Боб: «Верно. Это и есть эффект наложения в действии.»
Часть 3: Продвинутая структура версий
Теперь, когда мы понимаем основы версий и веток, давайте рассмотрим структуру версий более подробно.
Компоненты версии
Версия состоит из ревизий, которые могут быть:
- Целочисленные ревизии: Используются для последовательных, публичных версий (например,
1
или2.3
) - Ревизии в ветках: Именованные сегменты, используемые для веток и черновиков (например,
feature-x
в1.2.feature-x.3
)
Алиса: «То есть, у нас есть обычные нумерованные ревизии для основной линии и эти именованные ревизии для работы над фичами?» Боб: «Правильно. Целочисленные ревизии дают нам чистую, последовательную нумерацию для публичных версий, в то время как именованные сегменты позволяют создавать ветки для конкретных фич или экспериментов.» Алиса: «И они работают вместе в одной и той же структуре версий? Элегантно.» Боб: «Именно! Это дает нам единый способ выразить как линейный прогресс, так и параллельную разработку.»
Паттерны развития
Версии развиваются несколькими способами:
-
Совместимые изменения: Неломающее изменение обычно создает новую минорную ревизию.
- Редактирование версии
1.2
может создать1.2.1
,1.2.2
и т. д.
- Редактирование версии
-
Несовместимые изменения: Критические изменения влияют на совместимость на разных уровнях иерархии версий.
- В рамках одного префикса (например,
1.2.x
) разные ревизии могут быть несовместимы друг с другом, но они должны оставаться совместимыми со своим родителем (1.2
). - Если изменение нарушает совместимость с родительским префиксом, оно должно «подняться» на более высокий уровень. Например, изменение, нарушающее совместимость с
1.2
, создаст новую версию1.3
. - В случаях значительных структурных изменений версия может нарушить совместимость с несколькими уровнями, потенциально поднявшись до изменения мажорной версии (например, с
1.x
до2.0
). - Система определяет, насколько высоко должно «подняться» изменение, в зависимости от того, какие уровни префикса затронуты несовместимостью.
- Автоматическое обнаружение: Система автоматически обнаруживает несовместимости, анализируя изменения схемы между версиями Vibe. Когда несовместимость найдена, система определяет適切な уровень версии для увеличения, гарантируя соблюдение принципов семантического версионирования без необходимости ручного принятия решений.
Алиса: «То есть, мне не нужно самой выяснять, нарушает ли мое изменение совместимость с версией 1.2 или со всей версией 1? Система делает это за меня?» Боб: «Именно. Система анализирует ваши изменения и автоматически определяет, нужно ли вам небольшое повышение, например с 1.2.3 до 1.2.4, более значительное, как с 1.2 до 1.3, или даже изменение мажорной версии с 1.x до 2.0.» Алиса: «Это звучит гораздо безопаснее, чем если бы разработчики гадали о влиянии на совместимость.» Боб: «Так и есть. Это предотвращает как случайные критические изменения, так и ненужное завышение версий. Система гарантирует, что номера версий точно отражают реальные границы совместимости.»
- В рамках одного префикса (например,
-
Создание ревизий в ветках: При создании ветки в структуре версии одновременно добавляются два сегмента ревизии: именованный сегмент ветки и числовой сегмент.
- Когда разработчик ответвляет версию
1.2
для работы над фичей, создается версия вроде1.2.feature-x.0
. - Сегмент ветки (
feature-x
) идентифицирует линию разработки, а числовой сегмент (0
) позволяет вести последовательное версионирование внутри этой ветки.
- Когда разработчик ответвляет версию
Алиса: «Значит, когда я создаю ветку, я не просто добавляю имя, но и начинаю новую последовательность нумерации внутри этой ветки?» Боб: «Именно.
1.2.feature-x.0
показывает, что вы ответвляетесь от версии 1.2, а.0
дает вам отправную точку для вашей собственной последовательности ревизий в этой ветке.» Алиса: «И по мере внесения изменений в мою ветку я буду получать версии типа1.2.feature-x.1
,1.2.feature-x.2
и так далее?» Боб: «Совершенно верно. Ваша работа развивается с собственной нумерацией, при этом четко показывая связь с основной версией, от которой она ответвилась.»
Важно отметить, что ветки (например, main
или feature/new-login
) — это не то же самое, что ревизии в ветках внутри версий (например, feature-x
в 1.2.feature-x.0
). Ветки действуют как каналы публикации, которые контролируют, где виден Vibe, в то время как ревизии в ветках внутри версий определяют происхождение и историю разработки. Путь поиска координирует обе эти концепции — он определяет, в каких ветках искать, а также каким ревизиям в ветках отдавать предпочтение, когда доступно несколько версий.
Видимость веток и выбор версии
Путь поиска создает сложную систему разрешения, которая учитывает как ветки, так и ревизии в ветках, соблюдая при этом требования к версии:
-
Видимость веток: Vibe должен быть опубликован хотя бы в одной ветке из пути поиска, чтобы быть видимым вообще.
-
Требования к версии: Любые требования к версии в ссылке (например,
?1.2
) всегда должны быть удовлетворены, независимо от приоритета ветки. -
Критерии выбора: В наборе Vibe, удовлетворяющих требованиям к версии, система отдает приоритет на основе положения ветки в пути поиска:
- Приоритет веток: Vibe, опубликованные в ветках, которые стоят раньше в пути поиска, имеют высокий приоритет — до такой степени, что система выберет подходящий Vibe из более приоритетной ветки, даже если более свежие версии существуют в менее приоритетных ветках.
- Видимость ревизий в ветках: Ревизии в ветках внутри версий (например,
feature-x
в1.2.feature-x.3
) создают альтернативные линии разработки, которые видны, когда их имена совпадают с записями в пути поиска, но они все равно должны попадать в префикс версии, указанный в ссылке.
Алиса: «Этот приоритет веток звучит очень важно. То есть, если у меня путь поиска
['feature-x', 'main']
, система всегда предпочтет что-то из моей ветки, даже если вmain
есть более новая версия?» Боб: «Да, если это соответствует указанным вами требованиям к версии. Именно так и работает система наложения — ваши изменения имеют приоритет в вашем представлении.» Алиса: «А часть про ревизии в ветках просто делает вещи видимыми, но не переопределяет приоритет?» Боб: «Именно. Наличие совпадающего имени в версии может сделать что-то видимым, но приоритет в пути поиска определяется веткой, в которой это опубликовано. Ревизия в ветке создает альтернативную линию разработки, которую можно использовать для самых разных целей.» Алиса: «То есть, эти альтернативные линии разработки не только для работы над фичами?» Боб: «Вовсе нет. Их можно использовать для наложения различных конфигураций, расширения системы различными способами или в любой ситуации, где вам нужны параллельные версии одного и того же контента.»
Давайте рассмотрим несколько примеров с путем поиска ['feature-x', 'main']
при поиске common/button
:
-
Сценарий 1: Если
common/button
версии1.3
опубликован в веткеfeature-x
, он будет выбран вместо любой версии в веткеmain
(при условии, что он попадает в префикс версии, указанный в ссылке). -
Сценарий 2: Если
common/button
вообще не опубликован в веткеfeature-x
, система выберет совместимую версию из веткиmain
. -
Сценарий 3: Если
common/button
версии1.2.feature-x.3
опубликован в веткеmain
(обратите внимание, что ревизия в ветке совпадает с именем в пути поиска), эта версия видима, потому что ревизия в ветке создает альтернативную линию разработки, которая совпадает с записью в пути поиска. Однако она будет выбрана только в том случае, если попадает в префикс версии, указанный в ссылке.
Этот подход позволяет создавать альтернативные линии разработки для различных целей. Его можно использовать для разработки, создания безопасных пространств для редактирования и черновиков, наложения различных конфигураций или параллельного расширения системы. Механизм пути поиска гарантирует, что пользователи видят предпочитаемые ими линии разработки, бесшовно интегрированные с остальной частью системы.
Как в версии отображаются критические (несовместимые) изменения?
* [x] Путем увеличения номера основной ревизии (например, критическое изменение в `1.2.5` приводит к `1.3`).
* [ ] Путем добавления символа `!` в конец версии.
* [ ] Путем создания совершенно новой корневой версии (например, `1.2.5` становится `V2/1.0`).
* [ ] Путем преобразования целочисленных ревизий в текстовые.
Часть 4: Связываем все воедино — Ссылка aug:
Схема URI aug:
служит языком для навигации в этой версионированной и разветвленной реальности. Она предоставляет синтаксис как для простых запросов, так и для полностью разрешенных, зафиксированных ссылок, обеспечивающих идеальную воспроизводимость.
Компоненты ссылки aug:
Ссылка aug:
состоит из нескольких ключевых компонентов:
- Схема: Префикс
aug:
, который идентифицирует ссылку как Augmented-ссылку. - Ветка: Необязательное указание ветки (например,
~main/
), которое явно нацелено на ветку. - Разрешенная ветка: В полностью разрешенных ссылках — ветка, которая использовалась для разрешения (например,
~:staging
). - Путь: Текстовый идентификатор Vibe (например,
articles/common/button
). - Префикс версии: Необязательное ограничение версии (например,
?1.2
), которое указывает требования совместимости. - Разрешенная версия: В полностью разрешенных ссылках — точная версия, которая была найдена (например,
:1.2.3
). - Индикатор ошибки: Если разрешение не удалось, код ошибки (например,
!404
). - Фрагмент: Необязательный указатель на определенную часть внутри Vibe (например,
#schema/properties/name
). - Текстовый фрагмент: Необязательный идентификатор текстового фрагмента (например,
:~:text=exact%20text
), который указывает на конкретное текстовое содержимое внутри Vibe, в соответствии со стандартом Фрагменты текста.
Примеры:
aug:schemas/UserProfile
- Простой запрос последней версии.aug:~experiments/schemas/UserProfile
- Запрос специально из ветки «experiments».aug:/schemas/UserProfile
- Запрос специально из ветки «main» (сокращение дляaug:~main/schemas/UserProfile
).aug:schemas/UserProfile?1.2
- Запрос версии, совместимой с 1.2.aug:~:staging/schemas/UserProfile?1.2:1.2.staging.4
- Полностью разрешенная ссылка.
Двойная роль пути поиска
При разрешении ссылки путь поиска используется для сопоставления как с Веткой, так и с любыми ревизиями в ветках внутри Версии. Это та магия, которая заставляет работать личные черновики и ветки с фичами.
Рассмотрим путь поиска ['yarik', 'casino', 'core']
. При разрешении aug:articles/cows
система:
- Находит все Vibe
articles/cows
, опубликованные в веткеcasino
. - В этом наборе она видит версию
1.yarik.1
. Посколькуyarik
находится в пути поиска с наивысшим приоритетом, эта версия выбирается. - Если бы версии
yarik
не существовало, она бы нашла последнюю версию без специальной ревизии в ветке, например1.2
.
Алиса: «То есть, путь поиска смотрит не только на ветки, но и на имена ревизий в ветках внутри версий?» Боб: «Именно. Это и делает его таким мощным. Он может найти вашу работу, будь она опубликована в вашей личной ветке или просто имеет ваше имя в своей версии.» Алиса: «Это очень гибко. Я могу сделать свои личные изменения видимыми только для меня, продолжая работать в основной системе.» Боб: «В этом и идея. Это создает эти параллельные реальности, где каждый видит свою работу, бесшовно интегрированную с общей основой.»
Состояния ссылок
-
Неявный запрос («Просьба»):
aug:schemas/UserProfile?1.2
- Это запрос последней версии
UserProfile
, совместимой с префиксом1.2
, разрешаемый относительно текущего пути поиска.
- Это запрос последней версии
-
Явный запрос ветки:
aug:~main/schemas/UserProfile
- Префикс
~
указывает на явный запрос Ветки. Это запрос Vibe, опубликованного в веткеmain
, игнорируя остальную часть пути поиска для этого запроса. - Сокращение для ветки
main
: Явный запрос к веткеmain
можно сократить. Например,aug:~main/schemas/UserProfile
можно записать какaug:/schemas/UserProfile
. Начальный слэш действует как сокращение для~main/
.
- Префикс
-
Разрешенная ссылка («Ответ»):
aug:~:staging/schemas/UserProfile?1.2:1.2.staging.4
- Это постоянная, однозначная запись результата разрешения.
~:
указывает, что исходный запрос был неявным.staging
— это ветка из пути поиска, в которой был успешно найден Vibe.?1.2
— запрошенный префикс версии.:1.2.staging.4
— точная, полная Версия, которая была найдена.- Сокращение для ветки
main
: Для ясности веткаmain
считается веткой по умолчанию и явно не указывается в разрешенной ссылке. Например, если бы вышеуказанная ссылка разрешилась в веткеmain
, она была бы записана какaug:schemas/UserProfile?1.2:1.2.main.4
, опуская спецификатор~:main/
.
Важно отметить, что ветки (например, main
или feature/new-login
) — это не то же самое, что ревизии в ветках внутри версий (например, feature-x
в 1.2.feature-x.0
). Ветки действуют как каналы публикации, которые контролируют, где виден Vibe, в то время как ревизии в ветках внутри версий определяют происхождение и историю разработки. Путь поиска координирует обе эти концепции — он определяет, в каких ветках искать, а также каким ревизиям в ветках отдавать предпочтение, когда доступно несколько версий.
Часть 5: Полный рабочий процесс разработки
Эти концепции позволяют создать безопасный и эффективный рабочий процесс:
-
Ветвление: Разработчик начинает работу над Vibe с путем
processes/onboarding
, который имеет версию1.3
и опубликован в веткеmain
. Он «ответвляет» его для своей фичиnew-login
.- Система создает новую версию Vibe.
- Новая версия:
1.3.new-login.0
- Опубликовано в ветках:
["feature/new-login"]
- Путь поиска разработчика устанавливается на
['feature/new-login', 'main']
.
-
Разработка: Разработчик работает над своим Vibe, создавая версии
1.3.new-login.1
,1.3.new-login.2
и т.д. Ему нужна стандартная Инструкция «Отправить Email». Он ссылается на нее какaug:instructions/send-email
. Система поиска сначала проверяет наличие версии, опубликованной в веткеfeature/new-login
, ничего не находит и возвращается к поиску стабильной версии, опубликованной вmain
. -
Переопределение: Разработчику нужен собственный шаблон письма. Он ответвляет
records/email-templates/welcome
и сохраняет новую версию. Эта новая версия создается и публикуется в веткеfeature/new-login
с версией типа2.1.new-login.0
. Теперь его процесс автоматически подхватывает его собственный шаблон, потому что его ветка имеет высший приоритет в его пути поиска. -
Продвижение: По завершении работы разработчик «продвигает» свою работу. Vibe версии
1.3.new-login.2
копируется, его Версия «очищается» до1.4
, и теперь он публикуется в веткеmain
(например, его массивbranches
становится["main", "feature/new-login"]
). Теперь это новая стабильная версия. -
Волновой эффект: Другой
Process
ссылался наaug:processes/onboarding?1
. Поскольку новая версия1.4
совместима с префиксом?1
, в следующий раз, когда этотProcess
будет разрешаться, он автоматически и безопасно подхватит новую версию1.4
. Это контролируемое обновление является основной особенностью архитектуры системы.
Алиса: «Этот рабочий процесс очень хорошо продуман. То есть, я могу создавать ветки, работать в своем собственном пространстве, а затем продвигать свои изменения, когда они будут готовы?» Боб: «Да, и система берет на себя всю сложность, чтобы ваши изменения были видны вам во время разработки, а затем правильно интегрированы при продвижении.» Алиса: «А этот волновой эффект — это значит, что другие части системы автоматически получат мои обновления, если они совместимы?» Боб: «Именно. Если они запрашивали версию
?1
, они автоматически получат вашу новую1.4
. Но если бы они хотели что-то более конкретное, например,?1.3
, они бы не получили обновление, пока не изменили бы свою ссылку.»
Этот рабочий процесс, основанный на единой системе ветвления и версионирования, позволяет безопасно и эффективно вести параллельную разработку. Это основной механизм, который позволяет экосистеме Vibe развиваться контролируемым, предсказуемым и масштабируемым образом.
Продвинутые концепции и детали реализации
Ключевые моменты для запоминания
- Версии — это родословная:
1.2.feature.3
рассказывает историю ответвления от1.2
. - Двойной контроль видимости: Vibe может быть опубликован в ветке
main
, но иметь версию1.2.yarik.1
, гдеyarik
— это ревизия в ветке, которая делает его предпочтительно видимым для пользователей сyarik
в их пути поиска. - Путь поиска — это наложение:
['yarik', 'main']
означает «покажи мне работуyarik
поверхmain
». - Продвижение — это сокращение: Черновик
1.2.yarik.5
продвигается путем копирования в новую, более короткую версию, например1.3
. - Волновой эффект — это фича: Продвижение версии
1.3
будет подхвачено всем, что запрашивает?1
, что является предполагаемым путем обновления. - Фиксация для стабильности: Чтобы избежать волнового эффекта, запросите более конкретный префикс версии, например
?1.2
.
Алиса: «Эти ключевые моменты очень помогают. То есть, структура версии сама по себе рассказывает историю о том, как Vibe развивался?» Боб: «Именно. Просто взглянув на
1.2.feature.3
, вы понимаете, что это третья ревизия ветки, которая началась с версии 1.2.» Алиса: «А путь поиска — это как наложение моей работы поверх основной системы, как прозрачные слои.» Боб: «Это идеальная аналогия! Ваши изменения лежат сверху, и там, где вы ничего не меняли, вы как бы видите сквозь них основную версию, которая находится под ними.»