gitum

Устройство gitum

Содержание

Здесь записано, почему gitum устроен именно так: из каких задач он вырос, какие решения приняты и какие варианты отвергнуты. Как им пользоваться и что делает каждая команда — в руководстве; этот документ его не повторяет, а ссылается на него.

Задача

Вести свои изменения параллельно чужому апстриму и синхронизироваться с ним удобно и наглядно: в любой момент видно, где каждое наше изменение находится относительно апстрима.

Требования собраны из трёх реальных сценариев:

Решение было развивать gitum, даже если от прежнего кода останется одно название. Так и вышло: gitum 2 написан заново.

Чему научил wine-staging

wine-staging — работающий пример того же подхода: около 120 серий параллельно апстриму и почти 2000 коммитов «Rebase against SHA».

Им не хватает связи серии с MR и багами (кроме Fixes), автоматического определения принятия (тем более с правками), вариантов серии на разных базах, журнала разрешения конфликтов, машиночитаемого отчёта и работы в git-ветках: патчи правят как файлы, а собирают серию в дереве wine, чтобы проверить.

Отсюда два решения. Берём формат каталога серии и definition (gitum читает и пишет эту раскладку), граф Depends, базу как явный sha, коммит журнала на каждое состояние. Добавляем серию как обычную git-ветку (каталог в журнале генерирует gitum), метаданные, варианты на базах, отслеживание принятия и журнал конфликтов.

Модель: зачем три сущности

Слои складываются стопкой, потому что так устроены реальные форки: каждый следующий слой добавляет своё к предыдущему, и переносить их надо вместе.

Журнал: почему так хранится состояние

Что лежит в журнале, описано в руководстве: что переписывается, а что только растёт. Здесь — почему.

Принятые решения

Решения приняты 2026-11-11, когда начиналась работа над gitum 2, и уточнялись по ходу.

  1. Тонкая обёртка над git (subprocess), без GitPython. Всё, что нужно gitum, — rebase, cherry-pick с rerere, merge-tree, patch-id, update-ref --stdin — есть только в самом git. Библиотеки либо оборачивают тот же процесс git, либо не умеют этих операций, либо тянут скомпилированную зависимость. Обёртка прозрачна: в журнале прогона видна каждая команда git.
  2. Python ≥ 3.11 и никаких зависимостей, кроме git: tomllib есть в стандартной библиотеке. Пакет ставится и проверяется в любом дистрибутиве.
  3. gitum 1 не поддерживается: ни его команды, ни перевод старых репозиториев. Совместимость с его моделью (один слой, перенос апстрима по одному коммиту) мешала бы новой.
  4. Коды возврата для автоматизации: 0 успех (10 — обновлено, с --detailed-exitcode), 1 ошибка, 2 нужен человек, 75 занято. Ни одна команда ничего не спрашивает: где нужен ввод, она завершается с кодом 2 и говорит, что именно нужно. У каждой команды есть --json.
  5. Идентичность изменения хранится в журнале (changes/<id>.json), а не в trailer'е коммита. Изначально планировался обязательный Gitum-Id в каждом коммите, но тогда пришлось бы переписать сотни существующих коммитов. Теперь изменение узнаётся по trailer'у, если он есть, по соответствию sha при sync, по patch-id и по заголовку.
  6. Надёжность — главное требование. Любую операцию можно прервать в любой точке, после чего её можно продолжить или отменить, а следующая команда сама доделывает или откатывает прерванную фиксацию. Как это устроено — в разделе Надёжность руководства. Каждый новый путь проверяется тестами, которые убивают gitum на выбранном вызове git (GITUM_TEST_CRASH).
  7. Работа только в приватных рабочих деревьях. Чужое рабочее дерево gitum не сбрасывает и не чистит. Ветка, выбранная в чистом дереве, переносится вместе с ним; если в дереве есть изменения — код 2.
  8. Ссылки двигаются одной транзакцией в конце операции (update-ref --stdin с проверкой старых значений): либо все ветки, журнал и история обновились, либо ничего.
  9. Генерируемые слои пересобираются, а не переносятся (generator = "staging" или "command"). Слой из серий wine-staging правильнее собрать заново на новой базе, чем переносить его коммиты. Генератор staging воспроизвёл слой rebased-11.20 робота целиком, кроме configure, который зависит от версии autoconf.
  10. Python не узкое место. Почти всё время уходит на процессы git (5–12 мс каждый на репозитории размером с wine), сам Python занимает меньше 5%. Поэтому правило одно: не запускать git в цикле по объектам, а читать пачкой (cat-file --batch, один log на много коммитов). Это ускорило, например, status с 1,34 до 0,28 с.
  11. Тесты полного цикла запускаются при сборке пакета (%check): только git, без сети, во временных каталогах.

Решения по работе с апстримом

Чего не будет

История

Проверка на реальных данных (клон wine-rebased): слои basealt (15 патчей) и etersoft (156 патчей), перенесённые с 11.19 на 11.21, дали патчи, идентичные результату робота (154 из 156; два отсутствующих робот позже переделал). check-upstream нашёл принятый в wine-11.5 патч taskschd.