diff --git a/accessibility/docs/00-dev-setup.md b/accessibility/docs/00-dev-setup.md index 4d69fa8..b71f2c3 100644 --- a/accessibility/docs/00-dev-setup.md +++ b/accessibility/docs/00-dev-setup.md @@ -197,17 +197,21 @@ all 1838 files of a commercial title. Pushing it anywhere would distribute the game. Publishing therefore means: rebuild a separate repository that contains only the -mod, and force-push *that*. +mod, and push *that*. ``` sh accessibility/publish/publish.sh ``` -This clones the dev tree to `../alchemist-accessibility-publish`, runs -`git-filter-repo` to keep only `accessibility/` and `CLAUDE.md`, lifts +This clones the dev tree to `../alchemist-accessibility-publish` and runs +`git-filter-repo` over the clone with a single filename callback that does three +things at once: keeps only `accessibility/` and `CLAUDE.md`, lifts `accessibility/publish/README.md` and `install.patch` up to the root (so a visitor to the mod repo finds them where they expect), and drops the publish machinery -itself. +itself from the **whole history**. + +All three being one filter is what makes the rewrite deterministic, and that is +worth more than it sounds — see [Why this is not a force-push](#why-this-is-not-a-force-push). Then **the check that matters**: it lists every path in the rewritten history and aborts if anything that is not the mod or its docs survived. A clean run says: @@ -224,16 +228,43 @@ The script prints the push commands and stops rather than pushing for you: ``` cd ../alchemist-accessibility-publish git remote add origin https://code.iamtalon.me/talon/alchemist-accessibility.git -git push --force -u origin master +git push -u origin master ``` -`--force` is not a mistake and not a recovery step. `git-filter-repo` rewrites the -history from scratch every time, so the published commits are new objects on every -publish. The mod repo is derived output; force-pushing it is the normal path. - ⚠ Paste those as **separate lines**. If a shell wraps the `remote add` line, the URL ends up on its own and gets run as a command. +### Why this is not a force-push + +`git-filter-repo` is deterministic: given the same input commits and the same +filter, it produces byte-identical output commits, because it preserves author +and committer timestamps and a commit's SHA is a function of its tree and its +parents. Verified by running `publish.sh` twice into different directories and +diffing `git rev-list --all` — all 24 SHAs identical. + +So **a publish that only adds commits to the dev tree is a plain fast-forward**, +and pushes only the new objects. Git is content-addressed on top of that: the +bulk of the repo is the four wall-tone WAVs (~740 KB) and the Tolk DLLs +(~135 KB), and those blobs are keyed by content, so they are never re-uploaded +even when a rewrite does happen. + +It used to be a force-push every time, for a reason worth not reintroducing. The +script ended with a `git rm -r accessibility/publish` and a `git commit`, and +that commit was created fresh with the *current time* on every run — so the tip +SHA changed even when nothing else had, and the old tip was a sibling of the new +one rather than an ancestor. It was also not achieving much: `git rm` only +removes a file from the tip, so `publish.sh` was still present in every older +commit of the published repo. Filtering it out instead fixed both. + +**If the push is rejected as non-fast-forward, that now means something**: the +dev history itself was rewritten — an `amend`, a `rebase`, or a rebase onto a new +game version. `--force` is correct there, and the mod repo is derived output so +nothing is lost. But it should be a deliberate act, not the daily command. A +force-push you always run is a force-push you stop reading. + +⚠ The corollary, unchanged: any commit made **directly in the published repo** is +destroyed by the next publish. Always work in the development tree. + --- ## Rebasing onto a new game version