release-kit 0.2.2

A canonical release workflow: a technology-agnostic method, per-technology bindings, and the rk CLI that lands and serves them.
Documentation
# 07 — Branch for release

The style for older lines. Precondition: users cannot simply be moved forward — customers run pinned versions on their own infrastructure, a support contract covers an old line, or a sign-off gate stands before a ship. The [shared setup](./06-release-from-trunk.md) carries the same product and team; here the trunk is at H, and Carol's export feature is, in this scenario, unfinished and not flagged.

## Cutting the branch

A few days before the planned v1.1.0 release:

```bash
git checkout -b release/1.1 <commit> && git push -u origin release/1.1
```

```text
master:  A──B──C──D──E──F──G──H──J──K──L──…   work continues, no freeze
                              |
release/1.1:                  └──●            hardening only
```

Cutting the branch slows nobody down: J, K, and L merge to the trunk that same afternoon.

The branch point is chosen, and chosen need not mean latest. With Carol's unflagged half-finished work sitting at G, the branch is cut from F rather than H: the release branch is a snapshot of a trusted point on the trunk, and it can even be created retroactively, days later, from any commit or tag.

## Harden, then release

Validation runs against the branch. Automation tags `v1.1.0-rc.1` there, which builds the installers and publishes nothing to any registry; a human installs them and uses them. Suppose validation finds a pagination bug.

The wrong instinct is to fix it on `release/1.1`. Instead, the fix lands on the trunk first — test, fix, pull request, squash-merge as commit M — and then that one commit crosses:

```bash
git checkout release/1.1 && git cherry-pick M && git push
```

```text
master:  A──B──…──H──J──K──L──M
                  |           └────── cherry-pick
                  ↓                      ↓
release/1.1:      ●──────────────────────●
                rc.1                   rc.2
```

J, K, and L did not travel: a cherry-pick is not a merge, and only M crossed. CI now runs twice — once on the trunk guarding M, once on the branch guarding the cherry-pick. A duplicated pipeline per active line is the real cost of this style, and the reason not to use it without the precondition. When validation passes, automation tags `v1.1.0` on the branch and the release ships.

## The patch release

Two weeks later the empty-CSV bug is reported against v1.1.0, and the trunk is far ahead at T. The move is the same, one-directional: reproduce and fix on the trunk first — commit U — then cherry-pick U onto the branch; with CI green there, automation tags `v1.1.1`.

```text
master:  ──H──J──K──L──M──…──T──U
                     |           └── cherry-pick
                     ↓                  ↓
release/1.1:  ●──────●──────────────────●
                  v1.1.0             v1.1.1
```

Users on the 1.1 line get only the CSV fix; nothing else moved. That capability is the entire reason this style exists.

## The next release, and the death of the old line

When v1.2 is due, `release/1.1` is not reused: `release/1.2` is cut fresh from the trunk, and activity moves there while the old line's cherry-picks trend to zero. When 1.1 is out of production entirely:

```bash
git push origin --delete release/1.1
```

The tags must exist before the branch dies, or its commits dangle and are garbage-collected; a tag outlives its branch, which is what makes the deletion safe and the line recoverable. And `release/1.1` is never merged into `master`: everything on it arrived by cherry-pick from the trunk.

## The four ways the pattern breaks

- Fixing on the release branch, then merging down to the trunk. One merge is forgotten, and the bug regresses at the next branch cut. The one exception: a bug that truly cannot reproduce on the trunk is fixed on the branch and merged down, with the regression risk accepted knowingly.
- Merging the trunk into the release branch instead of cherry-picking. Pulling everything since the cut means the branch was cut on the wrong day.
- Keeping one eternal release branch across versions. Each line gets a fresh branch from the trunk.
- Merging one release branch into another. Never; each line takes its cherry-picks from the trunk independently.