Renaming ten repositories without breaking anything
Ten repositories moved to short names in one evening. The HA DNS lab
became dns, the managed network lab became netlab, the VPS lab became
vps-lab, the CSS DOOM experiment became css-doom, and several others
got the same treatment. Five of them are public. The other five are
private, and they stay unnamed here for a reason that shows up later.
Short names are easy to pick and annoying to apply. A repository name is a URL, a git remote, a Pages path, a README link, a local directory, and a line in a few tool configs. Any one of those left pointing at the old name is a broken link or a failed clone. The work was less about the renames and more about the sweep that follows them.
What GitHub redirects, and what it does not
GitHub redirects renamed repository URLs and git remotes. git pull on an
old remote keeps working, and a browser on the old repository URL lands on
the new one. That covers the obvious cases, and it makes a rename feel
safer than it is.
Pages project URLs do not redirect. A project site lives at
stayz3ro.github.io/<repository>/, and that path does not follow the
rename. After the CSS DOOM repository became css-doom, the old path
/css-doom-static-lab/ returned 404 while /css-doom/ served the site.
The redirect covers the repository, not the published path built from its
name.
That is the first lesson: redirects are per-object. Git has them. Pages does not, and neither does anything else that encodes the repository name in a URL.
The build that the rename exposed
The Pages problem was worse than the path. That site was still set to
“Deploy from a branch”, the legacy mode that serves files straight from
main. The real site is a Vite build. The rename triggered a legacy
rebuild that published raw source instead of the build output, so the
site’s JavaScript and CSS 404’d.
The fix shipped as a pull request: change the build --base to the new
path, switch the Pages source from the branch to GitHub Actions so the
workflow’s build is what gets served, merge, then check that the built
JavaScript and CSS return 200.
The --base value is the part that is easy to miss. A project site built
for /old-name/ keeps emitting /old-name/ asset URLs no matter how many
times it rebuilds. The rename only made the mismatch visible; the build
setting had been carrying the repository name the whole time.
One sweep pull request per repository
The mechanical cleanup was a pull request per repository for README links and titles. Every change was a rename: old name out, new name in, nothing else. To prove that, each diff was verified by undoing the name swap on every changed line. If reversing old and new reproduced the original text exactly, the line was a pure rename and not a stray edit riding along. Rename-only diffs should be provable, not asserted.
Local work took longer than the repository edits:
- Clone remotes were updated to the new URLs.
- Local folders were renamed to match, which meant chasing everything that pointed at the old paths: shell functions, tool configuration, editor project history.
- Git worktrees needed
git worktree repair. A worktree keeps a pointer back to its main checkout, and renaming the checkout directory breaks that pointer until it is rewritten.
The folder rename finds the most forgotten references, because the old
path was text in places that never appear in a repository. A shell
function that cds into the old directory is not part of any diff.
The slip
The first sweep’s commit message listed every renamed repository, including the private ones. That message landed on public pull request branches. A final review caught it.
The fix was to recreate the pull requests with clean messages and close the superseded ones. The files in those pull requests were fine; the messages were not. The rule that came out of it: no private repository names in any text attached to a public repository, including commit messages. File contents were already covered by habit. Commit messages were not, and they publish just as widely.
There is a second, smaller honesty point in that episode. Replacing a pull request after its messages have been visible is not the same as never having published them. The corrected branches are the right end state, but the earlier text was public and stays a disclosure.
What I would check next time
- Redirects cover git URLs and remotes. They do not cover Pages project paths, package registries, or anything else that encodes the repository name.
- A project-site build usually hardcodes its base path. Renaming the
repository without updating
--baseproduces a site that builds cleanly and serves broken assets. - Rename-only diffs can be proven by reversing the swap on each changed line.
- Local folder renames touch shell functions, tool configs, editor history, and git worktrees.
- Scan the commit messages, not just the files.
The renames themselves took one evening. The sweep is what made them stick.