90 lines
No EOL
5.2 KiB
Markdown
90 lines
No EOL
5.2 KiB
Markdown
|
||
# Jujutsu: Применение исправлений из stable во все ветки
|
||
|
||
Да, **Jujutsu** (`jj`) отлично справляется с этим workflow и делает его **проще**, чем в Git, благодаря своей архитектуре. Вот как это работает:
|
||
|
||
## Подход Jujutsu
|
||
|
||
Jujutsu не требует «переключения веток» в классическом понимании Git, потому что использует модель **working-copy-as-commit**. Вы можете редактировать любой коммит в репозитории напрямую без `checkout`.
|
||
|
||
## Workflow в `jj`
|
||
|
||
### Шаг 1: Во время разработки feature обнаружили баг в `stable`
|
||
|
||
Не нужно делать `stash` или коммитить незавершённую работу. Просто:
|
||
|
||
```bash
|
||
# Редактируем коммит в stable напрямую
|
||
jj edit <stable-commit-id>
|
||
# ИЛИ создаем новый коммит поверх stable
|
||
jj new stable
|
||
```
|
||
|
||
### Шаг 2: Делаем исправление
|
||
|
||
Вносим необходимые изменения (багфикс, оптимизация, рефакторинг). Эти изменения получают уникальный **change ID**, который сохраняется между ветками.
|
||
|
||
### Шаг 3: Применяем фикс ко всем нужным веткам
|
||
|
||
Здесь `jj` раскрывается во всей красе. Два основных подхода:
|
||
|
||
#### Вариант A: Rebase-based propagation
|
||
|
||
```bash
|
||
# Rebase feature веток на обновлённый stable
|
||
jj rebase -b feature-branch -d stable
|
||
jj rebase -b another-feature -d stable
|
||
```
|
||
|
||
#### Вариант B: Cherry-pick стиль (дублирование + rebase)
|
||
|
||
```bash
|
||
# Дублируем change с фиксом и rebase на каждую ветку
|
||
jj duplicate <fix-change-id>
|
||
jj rebase -r <duplicated-change-id> -d feature-branch
|
||
```
|
||
|
||
### Шаг 4: Селективное применение через revsets
|
||
|
||
Для исключения deprecated веток используем мощный язык **revset** в `jj`:
|
||
|
||
```bash
|
||
# Применяем ко всем веткам кроме deprecated
|
||
jj rebase -b 'branches() & ~(branches(glob:"deprecated*") | branches("old-feature"))'
|
||
```
|
||
|
||
## Ключевые преимущества `jj` для этого workflow
|
||
|
||
- **Без загрязнения рабочей директории**: Ваше текущее состояние разработки `feature` остаётся нетронутым, пока вы работаете над фиксом в `stable`.
|
||
- **Change IDs отслеживаются между ветками**: Одно и то же логическое изменение сохраняет свою идентичность при rebase или дублировании, что упрощает отслеживание применения фикса.
|
||
- **Автоматическое разрешение конфликтов**: При rebase нескольких веток с фиксом `jj` помогает выявлять и разрешать конфликты инкрементально.
|
||
- **Нет "detached HEAD" состояний**: В отличие от Git, вы можете свободно навигировать и редактировать любой коммит без риска потерять работу.
|
||
|
||
## Практический пример
|
||
|
||
```bash
|
||
# 1. Сейчас работаем над feature
|
||
jj log
|
||
|
||
# 2. Создаём фикс на stable
|
||
jj new stable -m "Fix critical bug in validation"
|
||
# Вносим изменения
|
||
jj commit
|
||
|
||
# 3. Получаем change ID вашего фикса
|
||
FIX_ID=$(jj log -r @ --no-graph -T 'change_id')
|
||
|
||
# 4. Rebase всех активных feature веток
|
||
jj rebase -b 'branches() & ~branches(glob:"deprecated*")' -d stable
|
||
|
||
# 5. Возвращаемся к работе над feature
|
||
jj edit feature
|
||
```
|
||
|
||
## Важные моменты
|
||
|
||
- **Разрешение конфликтов**: Если ваш фикс в `stable` конфликтует с изменениями в `feature`-ветках, `jj` создаст conflict markers, которые нужно будет разрешить для каждой ветки.
|
||
- **Принцип upstream-first**: Как и в GitLab Flow, всегда исправляйте сначала в самой upstream-ветке (`stable`), затем распространяйте downstream.
|
||
- **Состояние working copy**: После операций используйте `jj status`, чтобы увидеть, к какому коммиту привязана рабочая копия, и `jj edit <branch>` для возврата к работе над `feature`.
|
||
|
||
> Да, `jj` абсолютно поддерживает этот workflow и делает его более эргономичным, чем Git, устраняя накладные расходы на переключение контекста и предоставляя мощные revset-запросы для селективных операций с ветками. |