Skip to content
overterm
Documentation

Versioning

How versions are chosen, enforced by git hooks, cut into releases, and read in the changelog.

Overterm uses SemVer. The version lives in one file, VERSION, and every commit that changes the app bumps it in the same commit. That is enforced by a git hook rather than remembered, which is why the changelog has an entry for every version and no gaps.

What the parts mean

Part When
major something incompatible: a saved-state format older versions cannot read, a removed feature or shortcut
minor a new user-visible feature or capability
patch a fix, performance work, polish, or an internal step of a larger feature

The choice is about the change’s effect on someone using the app, not about how much code moved.

The hooks

make hooks points git at the repository’s own hooks, once per clone. There are two.

pre-commit refuses a commit that changes the app without a new VERSION. “The app” means anything under Sources/, Resources/ or Scripts/, or Package.swift, Makefile or mise.toml. The message tells you what to run:

Scripts/bump-version.sh minor "tabs: what changed"
git add VERSION CHANGELOG.md

SKIP_VERSION_CHECK=1 git commit … lets one through — needed when amending a commit that bumped it already, because the check compares against HEAD, which an amend replaces.

post-commit tags a commit that changed VERSION with an annotated v<version>. If that tag already exists elsewhere it says so and leaves it alone. Tags stay local until you push them.

bump-version.sh

Scripts/bump-version.sh major|minor|patch "area: what changed"

It sets VERSION one step past the committed version — so running it twice before a commit does not bump twice — and adds the line to CHANGELOG.md under a heading for the new version and today’s date. Run it again before committing and it adds another bullet to the same entry.

Commit VERSION and CHANGELOG.md with the change itself, not separately.

Cutting a release

Push the commit and its tag, then run the workflow by hand:

git push origin main --tags

GitHub → Actions → Release → Run workflow. A macOS runner tests, builds Overterm.app, packs a DMG, and publishes release v<version> with that version’s CHANGELOG.md entry as the notes. It refuses a version that is already released — bump first.

Nothing triggers it on push: a macOS runner is expensive, so releases are deliberate. Locally the same pieces are make app dmg and Scripts/release-notes.sh.

There is one scheduled workflow, and it is not about releases: once a week it checks whether Ghostty has tagged a release newer than the pinned one and opens an issue if so. Bumping the pin is by hand, because Xcode and Zig requirements move with it.

Reading the version you have

Overterm ▸ About Overterm shows, for example, “Version 2.14.0 (147)” — the version from VERSION, and in brackets the build number, which is the count of commits on the branch it was built from. Under it: the commit it was built from (with -dirty if the tree was not clean) and the day it was built.

⌥⌘O, View Latest Changelog, shows what the installed build added; the changelog is bundled into the app for exactly that. Settings ▸ About has the same thing, plus the update check.

The changelog

CHANGELOG.md on GitHub is the history, newest first, one heading per version with its date and one bullet per change. Release notes on the releases page are that version’s entry, generated from the same file — so there is one history, not two.

Reading it is worth a note: the bullets are written as the change, in the area it touched — overgit: the git panel in the sidebar, diff: the file-diff card, out of the changes pane. A run of patch versions with internal-sounding bullets is usually one feature being built; the minor version at the end of the run is the one that landed it.

Version 1.0.0 is the original import of the project, and its entry covers the commits up to that point.