gitum

gitum design

Contents

This document records why gitum is built the way it is: the problems it grew from, the decisions taken and the options rejected. How to use it and what each command does is in the manual; this document does not repeat it and links to it instead.

The task

Develop your own changes in parallel with somebody else's upstream and stay in sync with it conveniently and visibly: at any moment you see where each of your changes stands relative to the upstream.

The requirements come from three real scenarios:

The decision was to develop gitum further even if only its name survived. That is what happened: gitum 2 was written from scratch.

What wine-staging taught us

wine-staging is a working example of the same approach: about 120 series in parallel with the upstream and almost 2000 "Rebase against SHA" commits.

What it lacks: a link from a series to its MRs and bugs (beyond Fixes), automatic detection of acceptance (let alone with modifications), variants of a series on different bases, a record of conflict resolutions, a machine-readable report, and work in git branches: patches are edited as files, and a series is built in a wine tree to test it.

Hence two decisions. We take the series directory and definition format (gitum reads and writes this layout), the Depends graph, the base as an explicit sha, and a journal commit per state. We add the series as an ordinary git branch (gitum generates the directory in the journal), metadata, variants on bases, tracking of acceptance and a record of conflicts.

The model: why three entities

Layers are stacked because real forks are built that way: each layer adds its own on top of the previous one, and they have to move together.

The journal: why the state is stored this way

What the journal holds is in the manual: what is rewritten and what only grows. This section is about why.

Decisions

The decisions were taken on 2026-11-11, when work on gitum 2 began, and refined along the way.

  1. A thin wrapper over git (subprocess), no GitPython. Everything gitum needs (rebase, cherry-pick with rerere, merge-tree, patch-id, update-ref --stdin) exists only in git itself. Libraries either wrap the same git process, or lack these operations, or bring a compiled dependency. The wrapper is transparent: the run log shows every git command.
  2. Python ≥ 3.11 and no dependencies besides git: tomllib is in the standard library. The package installs and tests in any distribution.
  3. gitum 1 is not supported: neither its commands nor converting old repositories. Compatibility with its model (one layer, upstream moved one commit at a time) would hold the new one back.
  4. Exit codes for automation: 0 success (10 updated, with --detailed-exitcode), 1 error, 2 a person is needed, 75 busy. No command asks anything: where input is needed, it exits with 2 and says what exactly is needed. Every command takes --json.
  5. A change's identity is kept in the journal (changes/<id>.json), not in a commit trailer. A mandatory Gitum-Id in every commit was planned at first, but it would have meant rewriting hundreds of existing commits. Now a change is recognized by its trailer if it has one, by the sha mapping of a sync, by patch-id and by subject.
  6. Reliability is the main requirement. Any operation can be interrupted at any point; afterwards it can be continued or undone, and the next command finishes or rolls back an interrupted commit by itself. How it works is in Reliability in the manual. Every new path is tested by killing gitum at a chosen git call (GITUM_TEST_CRASH).
  7. Work happens only in private work trees. gitum never resets or cleans somebody's work tree. A branch checked out in a clean work tree moves together with it; with local changes there, exit code 2.
  8. References move in one transaction at the end of an operation (update-ref --stdin with checks of the old values): either all branches, the journal and the history are updated, or nothing is.
  9. Generated layers are rebuilt, not rebased (generator = "staging" or "command"). A layer made of wine-staging series is better built anew on the new base than moved commit by commit. The staging generator reproduced the robot's rebased-11.20 layer completely except configure, which depends on the autoconf version.
  10. Python is not the bottleneck. Almost all the time goes to git processes (5–12 ms each on a wine-sized repository); Python itself takes under 5%. So the one rule is: never run git once per object in a loop, read in batches (cat-file --batch, one log for many commits). For example, this took status from 1.34 to 0.28 s.
  11. The full-cycle tests run in the package build (%check): only git, no network, temporary directories.

Decisions about working with upstream

What gitum will not do

History

Checked on real data (a wine-rebased clone): the basealt (15 patches) and etersoft (156 patches) layers moved from 11.19 to 11.21 gave patches identical to the robot's result (154 of 156; the robot later redid the two missing ones). check-upstream found the taskschd patch accepted in wine-11.5.