
Коротко о главномРазвернутьСвернуть
- Проект Jujutsu 3 сентября в 07:47 мск выпустил версию 0.
- 0 своей системы контроля версий jj , которая работает поверх обычного Git-репозитория.
- Главное в релизе новая команда jj converge : она находит расходящиеся версии одного изменения и заменяет их одним коммитом, сама подбирая решение и спрашивая пользователя только там, где эвристики не справились.
Проект Jujutsu 3 сентября в 07:47 мск выпустил версию 0.45.0 своей системы контроля версий jj , которая работает поверх обычного Git-репозитория. Главное в релизе новая команда jj converge : она находит расходящиеся версии одного изменения и заменяет их одним коммитом, сама подбирая решение и спрашивая пользователя только там, где эвристики не справились.
Для тех, кто уже пользуется jj, это закрывает самую неприятную бытовую проблему инструмента, а два ломающих изменения в том же релизе стоит проверить сразу после обновления: команды jj config с флагом --user больше не спрашивают, какой файл править, а jj git import перестал подтягивать коммиты из отсоединённого HEAD в репозиториях без совмещения с Git. Предыдущая версия 0.44.0 выходила 6 августа, релизы у проекта идут примерно раз в месяц.
Откуда в jj берутся расходящиеся коммиты
В jj у каждого изменения есть постоянный change ID, который переживает перезапись коммита: можно поправить старый коммит в середине стека, и потомки перебазируются автоматически. Расхождение, или divergence, возникает, когда одно и то же изменение оказалось переписано дважды по разным веткам истории операций. Типичный сценарий: правка в двух рабочих пространствах, откат через jj undo после того, как часть работы уже ушла дальше, или неудачный конфликт при синхронизации с удалённым Git-репозиторием. В логе это выглядит как два коммита с одинаковым change ID, и до 0.45 их приходилось сводить руками через jj abandon , jj squash и jj rebase .
Что делает jj converge на самом деле
По описанию команды в исходниках, jj converge берёт ревизии из аргумента --revisions или из настройки revsets.converge , группирует их по change ID и считает расходящимися те группы, где ревизий больше одной. Если расходящихся изменений несколько, команда спросит, какое сводить. Дальше она применяет эвристики, чтобы собрать новую ревизию, а если те дали неоднозначный результат, задаёт вопросы: объединить ли описания, каких родителей выбрать и, в редких случаях, кого считать автором.
Когда решение найдено, новая ревизия заменяет расходящиеся, потомки перебазируются на неё, а локальные закладки, указывавшие на любую из старых версий, переезжают на новую. Два ограничения авторы оговаривают прямо. Во-первых, сводятся только ревизии, попавшие в revset: если у того же change ID есть видимые версии вне выборки, расхождение уменьшится, но не исчезнет. Во-вторых, в результате могут появиться файловые конфликты, даже если до этого их не было. Проверить, что именно сделала команда, можно через jj op show -p , посмотреть историю изменения через jj evolog , а откатить всё одним jj undo .
Режим --no-interactive нужен для скриптов и хуков: если без вопроса не обойтись, команда не зависнет в ожидании ввода, а прервётся с предупреждением.
Что сломается после обновления
Первое ломающее изменение касается конфигов. Раньше jj config edit --user , set --user и unset --user при нескольких пользовательских файлах, например ~/.config/jj/config.toml плюс каталог conf.d/ , спрашивали, какой файл править. Теперь они молча берут первый загруженный. Если у вас конфиг разложен по нескольким файлам, нужный указывается явно:
jj config set --file ~/.config/jj/conf.d/ui.toml ui.default-command logВторое касается репозиториев, где jj живёт рядом с Git, но не в колоцированном режиме, то есть .jj и .git не делят один рабочий каталог. jj git import в них больше не импортирует коммиты с отсоединённого Git HEAD. Если рабочий процесс опирался на то, что jj подхватит коммит, сделанный в Git в состоянии detached HEAD, теперь такой коммит нужно закрепить веткой или тегом на стороне Git.
Внутреннее изменение, которое тоже стоит знать: состояние Git HEAD теперь хранится отдельно для каждого worktree. Это подготовка к поддержке нескольких Git worktree в колоцированных репозиториях, когда у каждого рабочего пространства jj свой HEAD. Существующие репозитории мигрируют автоматически при первом запуске новой версии.
Исправления, которые заметят те, кто уже обжигался
- В колоцированных репозиториях git add после команды jj больше не оставляет в индексе устаревший cache-tree, из-за которого git fsck ругался на duplicateEntries . Уже испорченные репозитории исправление не лечит.
- Ctrl+C в пейджере less теперь выходит чисто: во флаги по умолчанию добавили -K , раньше терминал мог остаться в raw-режиме с мусором из escape-последовательностей.
- Сторона конфликта, оканчивающаяся на символ возврата каретки, больше не теряет этот байт при повторном разборе материализованного конфликта.
- jj run останавливается на первой ревизии, где процесс завершился с ненулевым кодом, вместо того чтобы идти дальше.
- Набор immutable_heads() по умолчанию теперь включает untracked_remote_tags() ; jj bisect предупреждает, когда из-за пропусков не может однозначно назвать первую плохую ревизию; починен краш jj log на скрытых ревизиях с revset log-graph-prioritize .
Как обновиться
Готовые сборки для Windows, macOS и Linux лежат на странице релиза, вариант с musl должен работать на любом дистрибутиве. По документации установить последний релиз можно так:
# бинарник последнего релиза через cargo-binstall
cargo binstall --strategies crate-meta-data jj-cli
# сборка из исходников, нужен Rust 1.88 и новее
cargo install --locked --bin jj jj-cli
# Homebrew
brew install jj
# Arch Linux
pacman -S jujutsuКому обновление ничего не изменит: тем, кто держит jj в одном файле конфига и работает только в колоцированных репозиториях. Им достанется jj converge и исправления, а ломающие изменения не затронут. Следующий сигнал, за которым стоит следить, это планируемая поддержка нескольких Git worktree, под которую в 0.45 подготовили хранение HEAD.
Источники: Релиз jj v0.45.0 на GitHub , Документация: установка и настройка jj 0.45 , Исходник команды converge (описание в cli/src/commands/converge.rs)
Изображение на обложке: Логотип: J. Jennings, CC BY 4.0


