Today, I’m working on a project that intends to both rename a Go module and cut a v2 release (all while keeping
main as the default branch). Why do both? Essentially rebranding without losing existing links.
In any case, before attempting this level of shenanigans, I wanted to make sure that it worked (spoiler alert: it did). Below are the steps I followed that got me there using a dummy repository:
Have existing module at some v1.x.x release.
I waited until pkg.go.dev picked up the changes to be sure, but this could also be verified by querying the Go module proxy:
$ curl https://proxy.golang.org/github.com/rodaine/modulemagic@v/list v1.0.0 v1.0.1
For support reasons, we intend to still maintain the
v1.x.xreleases for any sort of bug fixes and the like, just not new features. Splitting the trunk to a
v1branch allows that git history to continue. Tags are independent of branches and are tied directly to a commit so this is free and has no impact on the Go module.
To be on the safe side, I also set up GitHub branch protections on both
v1to make sure these branches aren’t accidentally damaged. GitHub (blessedly) remembers everything, so recovery is always possible, but better to avoid that kind of “oh, s#!%” moment if you can. There’s also a beta for something called repository rulesets which lets you protect a pattern of tags or branches with similar rules provided by the branch protections. Worth checking that out as well. Don’t want someone accidentally removing or changing a tag.
v2in a new branch off
This is a temporary
v2branch for the new code, so in case we have issues getting everything squared away,
mainhasn’t (yet) been polluted. Here we replace the
go.modimport path with the new module name suffixed with “/v2”, and update the code accordingly. At this point, make sure CI is still functional.
I would not tag the
v2.0.0release on this branch. To avoid rebase/merge situations, we only want to add tags to commits on
main(or, for legacy support, on
v1). Unless we get lucky with a fast-forward, tags changing references will potentially misalign with
go.mod.sumand cause a world of hurt downstream.
Rename, merge & release
Once satisfied with the code, use the GitHub repository settings UI to rename the repo to the new desired module name. GitHub automatically maintains redirects from the old name to the new one. Pleasantly, it maintains redirects for the entire name history of a repository. (This will be the third rename of this repository, and I strongly don’t recommend ever having to do this if you can avoid it.)
main, and tag the
v2.0.0. You can once again verify this on the module proxy:
$ curl https://proxy.golang.org/github.com/rodaine/renamedmodule/v2/@v/list v2.0.0
Revel in your Go module chicanery
🎉 ~ Despite the two modules being collocated in the same repository,
go getblocks fetching the original module as
v2and the new module as
v1due to the name mismatch in the
go.modfiles. pkg.go.dev takes its sweet time updating, but will eventually resolve the new module.