hyperion/10-linux/00-utils/jj/Untitled.md
2025-11-22 17:48:07 +03:00

90 lines
No EOL
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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-запросы для селективных операций с ветками.