Pimp My IDE / garage dispatchBack to the garage
13 Oct 2026 / Git / deployment records

One release ref can carry the whole history.

Thousands of deployment tags turn a useful audit trail into ref clutter. A linked chain keeps one moving pointer and makes the old releases ordinary Git history.

One ref per targetHistory in commitsRollback stays exact

A good audit trail can become a bad index.

Mark Dominus describes a monorepo that created one Git tag for every deployment target, application, timestamp, and released tree. The tags kept a complete deployment record. After thousands of releases, ref lookup slowed down and routine command output filled with release names.[1]

The naming convention also carried data that Git could not validate. To answer "what ran before this release?" the release system had to list every tag, filter the names, sort the timestamps, and select the previous entry.

Keep the audit trail. Stop making every old release a permanent dashboard switch.

Use commits for history and a ref for the head.

The proposal gives each deployment target one ref, such as refs/release/prod.app. That ref points to the newest release-record commit. Each record uses its first parent for the previous release record and its second parent for the exact application commit that ran.[1]

Git already knows how to walk commit parents. git log can list the release chain. HEAD^2 selects the current released commit. HEAD~1^2 selects the previous one. A diff between those two commits answers what changed without parsing timestamped ref names.

The plumbing supports the shape. git commit-tree creates a commit from a tree and accepts more than one parent. Git defines such a commit as a merge between lines of history.[2]

Move the pointer with a guard.

A release record is useful only if concurrent publishers cannot silently overwrite each other. git update-ref <ref> <new> <old> updates the ref only when its current object ID still matches the expected old value. Its standard-input mode can apply several ref changes together.[3]

That compare-and-swap check belongs in the release path. It does not make the deployment immutable. A user with permission can still delete or rewrite the ref and its history. Protect the namespace, retain remote logs, and decide who can repair a broken chain.

We tested the graph, not a production release system.

We built a disposable Git repository with a root record, two application commits, two release-record commits, and one release ref. The current record's second parent resolved to the second application commit. The previous record resolved through the first-parent chain. A guarded update-ref left the ref on the expected new record.

The fixture produced one ref for two release records. A diff between the two second parents reported one file changed, with one insertion and one deletion. This proves the graph and commands work in a small repository. It does not measure ref performance, remote push races, access control, garbage collection, or disaster recovery.

Keep the human changelog separate.

A deployment ledger answers what ran, where, and when. A changelog explains notable changes to people. Keep a Changelog says a changelog should be curated and should not be a dump of Git history.[4] One record should not do both jobs.

Adopt the chain only if release refs are a measured problem or if previous-deployment queries are brittle. Start with one noncritical target. Verify the current release, previous release, diff, rollback, concurrent update failure, export, and restore. The drive chain below drafts that test sheet. It does not publish a ref or approve a rollout.

Interactive makeover / release history drive chain

Pull one query at a time.

A tag pile makes the operator filter names and timestamps. This selector maps common release questions to one chain. It also keeps the required proof beside the command. The sample object names are invented teaching data.

Resolve refWalk recordSelect releaseAttach proof

Release query

Choose one question. The native radio group controls the chain, command, and receipt.

Selector detents

Test requirements

Selecting these items adds requirements to the test sheet. It does not record a pass.

Linked release readout

The first-parent rail moves through records. Each second-parent branch points at deployed code.

R-02
Previousrelease parent A1
R-03
Currentrelease parent B7
REF
prod.apppoints to R-03
git rev-parse refs/release/prod.app^2

Resolve the application commit attached to the newest release record.

Sources read / 13 Oct 2026

Source log

Open the evidence boundary
  1. Mark Dominus, "Maybe a better way to track the release history of a Git repo", published October 6 and read October 13, 2026. This is the source for the production problem, the one-ref linked-record proposal, the parent layout, and example history queries. The author labels the design as a 2019 proposal that was not adopted and may have unknown drawbacks.
  2. Git documentation, "git-commit-tree", version 2.56.0 documentation read October 13, 2026. It defines commit creation from a tree, standard-input messages, and multiple parents.
  3. Git documentation, "git-update-ref", version 2.56.0 documentation read October 13, 2026. It defines guarded updates that verify the old object ID and transactional standard-input updates.
  4. Keep a Changelog 1.1.0, read October 13, 2026. It distinguishes a curated changelog for people from a raw Git log.
  5. Hacker News item 50067721, resolved through the Hacker News API and read October 13, 2026. It maps the current discussion to the exact article URL. Product claims come from the sources above.

Evidence boundary: we exercised a two-release version of the graph in a disposable local repository with Git 2.43.0. We verified one ref, two linked records, second-parent release selection, a release-to-release diff, and a guarded update. We did not benchmark thousands of refs, test a remote race, configure access control, simulate garbage collection, or restore a damaged production ledger.