Strip legacy compatibility once every repo is migrated #35
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
We are the only consumer. Once every repo holding collab data is on the current format, all the backward-compatibility handling accumulated during pre-release is dead weight and should go.
The surface, excluding genuine interop:
NOT to remove: the RSA key-format handling in server/ssh/auth.rs (ssh-rsa vs rsa-sha2-256/512). That is interop with OpenSSH clients, not with old git-collab data.
SEQUENCING - doing this early destroys data silently:
c65ac0e2).Step 3 is the one that is easy to forget. A remote left holding bare refs becomes unreadable the moment the migration code is gone, and there is no error message that would explain why.
Migrated from git-collab issue
e5096ffcd17d34bf771d28acbc81175b46d6f106.Original author: a73x dev@a73x.sh.
Close reason: merged in patch
bf948322Step 3's order is wrong, and the push does not merely lag — it is rejected.
The remote holds
refs/collab/patches/<id>as a ref; the new layout needsrefs/collab/patches/<id>/events, a directory of the same name. Git cannot hold both. Reproduced against a local bare remote:So the deletion has to come first: sync cannot push the new layout for those 5 patches until the bare refs are gone. Reordered, step 3 is: delete the stale bare refs from both remotes, then sync.
Three things make this hard to diagnose, all verified:
git push --dry-runreports[new reference]for a push the server then rejects. The obvious way to check gives a false all-clear.4471ef75), so reads look completely healthy. Only writes are wedged, and nothing surfaces that until a push.print_sync_summary(sync.rs:276) ends with "Runcollab sync --remote Xagain to retry", which for a refname conflict can never succeed — the state is permanent until someone deletes remote refs. It also names a binary that does not exist; it should begit-collab sync.Worth doing before the strip: teach sync to recognise a refname conflict under
refs/collab/patches/and say what it actually means, rather than advising a retry that cannot work.Step 3 is done for
origin, 2026-08-10.The five stale bare refs were deleted and
syncthen went clean. Remote and local now agree exactly: 27 patch refs each, 9events+ 18rev/<oid>, zero bare<id>.Order confirmed as the comment above predicted: deletion first, then sync. The push retried from the pending store and succeeded on the same run.
Correction to my earlier note in this issue:
a73xdoes not hold stale refs — it holds no collab refs at all, and itsmainis at2e84decewhile local isf9785c8. So it is not blocked, it is simply unsynced. Step 4 still needs it, and any other clone, checked before the strip.The diagnostic that made this legible is patch
bf187d71(866b28c5), merged.Step 4 is satisfied for every known repo, 2026-08-10. Audited all three for legacy ref shapes — bare
<id>and the interim<id>/r/<n>:All three now agree exactly.
a73xhad no collab refs at all until today's sync, so it was never on a legacy shape;originwas cleared by the deletion recorded in the comment above.The archive namespace holds only
archive/issues/<id>, whose shape never changed, and noarchive/patchesexists on either remote — so archived patches are not a second migration surface today. Worth re-checking before the strip if any patch gets closed in the meantime, sinceclosemoves the whole subtree.Remaining caveat, unchanged: this covers the repos I can reach. A clone on another machine that has not synced since the migration would still hold bare refs, and after the strip it becomes unreadable with no error message that would explain why. That risk is now the only thing between here and step 5.
Not starting the strip yet — it touches state.rs, patch.rs and event.rs, which three in-flight patches are editing. Queued behind them deliberately.
Blocking finding from the live server, 2026-08-13. The strip cannot proceed as written without deciding what happens to
waystty.Server upgraded to
b2db9cfandgit-collab-server migraterun. Result:So step 3 is done for every repo the server hosts, and step 4's audit now covers the deployment as well as the two remotes. But migrating
waysttysurfaced what those 11 patches actually are:Zero revision refs, because all 11 patches use conventions this issue proposes to delete. Every revision on every one of them:
commit: ""— the''-means-unknown convention (patch.rs:28, state.rs:611), listed in this issue for removal. 11 of 11.base: null—PatchState.base_commitasOptionand theeffective_basesearch-back fallback, also listed. 11 of 11.These are April 2026 patches, predating revision commits being recorded. There is no data to recover: the commits were never stored, so no migration can pin them and no
rev/<oid>ref can exist. The objects may never have been pushed to the server at all.So stripping the legacy conventions makes 11 real patches unreadable, or readable-but-wrong, depending on how the code fails. The sequencing in this issue assumed legacy ref shapes were the only thing to migrate; legacy field conventions inside otherwise-current refs are a second surface it does not mention, and
waysttyis entirely made of them.Options, none of which are free:
''-means-unknown andbase: Nonehandling permanently. Cheapest, and honest: these patches genuinely have no commit, so a representation for "unknown" is not legacy debt but a real state.waysttyexplicitly, having looked at what those 11 patches are worth.Step 5 should not start until this is decided. Recommend option 1 unless the patches turn out to be worthless, in which case say so on the record rather than discovering it after the strip.
Decision, 2026-08-14: strip what has zero users, keep what still has data depending on it.
The audit after clearing
waystty(all five server repos, plus this clone):Strip — zero remaining users anywhere:
''-means-unknown convention forRevision.commit(patch.rs:28, state.rs:611) and the dedup that skips such revisions.waysttywas the only holder and its patches are deleted.migrate_patch_layout,resume_interrupted_migrationsand the three ref shapes. Every repo is migrated: local, both remotes, and all five on the server, confirmed bygit-collab-server migratereporting5 already currentand bygit-collab refs.collab_test.rsthat only pass viacreate_branch_patch's placeholder commit.event.rs:65legacy signature round-tripping,event.rs:98/state.rs:635/state.rs:656reviews withrevision: Noneand the vote-dedup special cases,state.rs:990the singular-stringrelates_todeserializer,PatchState.labelsserde(default)— subject to the implementer confirming each has no live data, the same way this audit did.Keep —
PatchState.base_commitasOptionand theeffective_basesearch-back fallback. 5 live revisions in this repository, from beforebasewas recorded per revision. Removing it breaks interdiffs on our own history.The reasoning is not only "there is data": "this revision has no recorded base" is a real state, not a transitional artefact. A revision recorded before the field existed genuinely has no base, and no migration can invent one. A representation for unknown is therefore permanent, and calling it legacy debt was my mistake.
Not to remove, unchanged from the issue: the RSA key-format handling in
server/ssh/auth.rs. That is interop with OpenSSH clients, not with old git-collab data.Verification requirement for whoever does this: use
git-collab refsandgit-collab-server refs --config …— both landed today for exactly this — rather than hand-writtenawk. Re-run the audit immediately before stripping, not from these numbers, since any sync could introduce a legacy shape from a clone that has not been looked at.