Git history: standardise on Conventional Commits; decide on Phase-era cleanup #34

Closed
opened 2026-08-30 12:50:29 +02:00 by orkun · 1 comment
Owner

Problem

Git history is inconsistent and noisy. Of ~80 commits, ~53 are old
Phase Nx: … / Merge Phase Nx: … pairs from the pre-self-hosting era:

96d01e4 Merge Phase 8b: modern primitive names
d330168 Phase 8b: modern names for the raw-memory and OS/IO primitives
6f1ba2c Merge Phase 8a: fixeds/ptrs indexing
...

while recent history has switched to clean Conventional Commits
(feat(stdlib): …, refactor(lang): …, ci(docs): …). The mix of a
merge-per-phase pattern and squashed conventional commits makes the log hard to
read and git bisect/git log less useful.

Proposal

  • Going forward: standardise on Conventional Commits, document it in
    CONTRIBUTING.md, and (optionally) enforce via a commit-msg hook
    (tools/git-hooks/ already exists) and/or CI.
  • History (optional / discuss first): the pre-self-hosting Phase era could
    be tidied, but rewriting shared history is disruptive. Options, in order of
    safety:
    1. Leave old history as-is; only enforce the convention from now on.
    2. Squash-and-annotate the historical phases behind a clear
      v0 baseline tag so the messy prefix is bracketed.
    3. Full rewrite (only if the repo is effectively single-author and everyone
      re-clones).

Because a rewrite is destructive and non-reversible for anyone who has cloned,
this needs an explicit decision before any filter-repo/rebase is run — do
not rewrite pushed history without sign-off.

Acceptance criteria

  • Commit convention documented and (optionally) hook/CI-enforced.
  • Decision recorded on whether/how to tidy historical Phase commits.
  • If rewriting: coordinated, tagged baseline first, and announced.

Part of the repository-cleanup / DX pass.

## Problem Git history is inconsistent and noisy. Of ~80 commits, **~53** are old `Phase Nx: …` / `Merge Phase Nx: …` pairs from the pre-self-hosting era: ``` 96d01e4 Merge Phase 8b: modern primitive names d330168 Phase 8b: modern names for the raw-memory and OS/IO primitives 6f1ba2c Merge Phase 8a: fixeds/ptrs indexing ... ``` while recent history has switched to clean Conventional Commits (`feat(stdlib): …`, `refactor(lang): …`, `ci(docs): …`). The mix of a merge-per-phase pattern and squashed conventional commits makes the log hard to read and `git bisect`/`git log` less useful. ## Proposal - **Going forward:** standardise on **Conventional Commits**, document it in `CONTRIBUTING.md`, and (optionally) enforce via a commit-msg hook (`tools/git-hooks/` already exists) and/or CI. - **History (optional / discuss first):** the pre-self-hosting `Phase` era could be tidied, but rewriting shared history is disruptive. Options, in order of safety: 1. Leave old history as-is; only enforce the convention from now on. 2. Squash-and-annotate the historical phases behind a clear `v0` baseline tag so the messy prefix is bracketed. 3. Full rewrite (only if the repo is effectively single-author and everyone re-clones). Because a rewrite is destructive and non-reversible for anyone who has cloned, **this needs an explicit decision** before any `filter-repo`/rebase is run — do not rewrite pushed history without sign-off. ## Acceptance criteria - [ ] Commit convention documented and (optionally) hook/CI-enforced. - [ ] Decision recorded on whether/how to tidy historical `Phase` commits. - [ ] If rewriting: coordinated, tagged baseline first, and announced. Part of the repository-cleanup / DX pass.
orkun added the
priority:low
area:repo
cleanup
labels 2026-08-30 12:50:29 +02:00
orkun closed this issue 2026-08-30 22:30:47 +02:00
Author
Owner

Done in 709465c — and the new commit-lint job went green on the push that added it (conventional-commits ✓), so it's live and gating.

Decision recorded (now in CONTRIBUTING.md → "Git history"): the pre-self-hosting Phase Nx: history stays as-is. A filter-repo/rebase rewrite is destructive and non-reversible for anyone who has cloned, and buys little — so we don't rewrite pushed history. The convention is enforced going forward; both the hook and the CI lint skip merge commits, so the old Merge Phase … pairs never trip it. The safe, non-destructive version of the issue's "bracket the messy prefix" (Option 2) falls out of the versioning work in #33: its first release tag doubles as a clean v0 baseline, no commit touched.

Enforcement, both halves the issue asked for:

  • Hook — tools/git-hooks/commit-msg rejects a non-conforming summary; tools/git-hooks/lib.sh holds the single rule (types, optional scope, ! for breaking, and merge/revert/autosquash exemptions). One-line enable, per clone: git config core.hooksPath tools/git-hooks (also turns on the fmt pre-commit hook).
  • CI — .forgejo/workflows/commit-lint.yml runs lint-range.sh over the new commits on every push and PR, sharing that same lib.sh so the two can't drift.

Also fixed a latent bug: the existing pre-commit fmt hook pointed at build/ludic-fmt, but the toolchain moved its binaries to bin/ a while back — so the hook silently no-op'd (its [ -x "$FMT" ] || exit 0 guard). It now finds bin/ludic-fmt and actually runs.

Verified: the hook accepts feat/fix/ci/refactor(!)/merge/revert and rejects added regex / Fix bug / WIP; lint-range.sh passes recent history and flags the old Phase 8b: commit; and CI linted this very change clean.

CONTRIBUTING.md now carries the full type/scope table and the enable step.

Acceptance criteria:

  • Commit convention documented and hook + CI-enforced.
  • Decision recorded on the historical Phase commits (leave as-is; bracket via #33's v0 tag).
  • No history rewrite performed (by decision).
Done in 709465c — and the new commit-lint job went green on the push that added it (`conventional-commits` ✓), so it's live and gating. **Decision recorded** (now in CONTRIBUTING.md → "Git history"): the pre-self-hosting `Phase Nx:` history **stays as-is**. A `filter-repo`/rebase rewrite is destructive and non-reversible for anyone who has cloned, and buys little — so we don't rewrite pushed history. The convention is enforced *going forward*; both the hook and the CI lint skip merge commits, so the old `Merge Phase …` pairs never trip it. The safe, non-destructive version of the issue's "bracket the messy prefix" (Option 2) falls out of the versioning work in #33: its first release tag doubles as a clean `v0` baseline, no commit touched. **Enforcement, both halves the issue asked for:** - **Hook** — `tools/git-hooks/commit-msg` rejects a non-conforming summary; `tools/git-hooks/lib.sh` holds the single rule (types, optional scope, `!` for breaking, and merge/revert/autosquash exemptions). One-line enable, per clone: `git config core.hooksPath tools/git-hooks` (also turns on the fmt `pre-commit` hook). - **CI** — `.forgejo/workflows/commit-lint.yml` runs `lint-range.sh` over the new commits on every push and PR, sharing that same `lib.sh` so the two can't drift. **Also fixed a latent bug:** the existing `pre-commit` fmt hook pointed at `build/ludic-fmt`, but the toolchain moved its binaries to `bin/` a while back — so the hook silently no-op'd (its `[ -x "$FMT" ] || exit 0` guard). It now finds `bin/ludic-fmt` and actually runs. **Verified:** the hook accepts `feat`/`fix`/`ci`/`refactor(!)`/merge/revert and rejects `added regex` / `Fix bug` / `WIP`; `lint-range.sh` passes recent history and flags the old `Phase 8b:` commit; and CI linted this very change clean. CONTRIBUTING.md now carries the full type/scope table and the enable step. Acceptance criteria: - [x] Commit convention documented and hook + CI-enforced. - [x] Decision recorded on the historical `Phase` commits (leave as-is; bracket via #33's v0 tag). - [x] No history rewrite performed (by decision).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: workshopsoft/ludic#34
No description provided.