How to (not) rename a public module
(Side note: This is a follow-up, and a more detailed discussion of How to rename or relocate a public Go module.)
Renaming a module? How's that a problem? If you want to rename a private module only used in your projects, renaming is indeed quite straightforward, at least with support from the IDE or a bash script.
But what if your module is public, and used by hundreds or thousands of client projects? (In this case, congrats to you.) Simply renaming the module would break tons of imports, so you need a plan.
Do you really need to rename the module?
Step 0: Think hard if the module really, really needs a new name (or a new path). Your users are used to the current import path, so why not leave the module path alone?
There are, of course, legitimate reasons for a change. For example, the project moves over to another organization. Or you discovered that the module name is a nasty word in Kenyan or Icelandic, like an insult of the king or the equivalent of one of those four-letter words. (As a rule of thumb: don't insult a king, and don't swear and curse in public, except if your target audience expects this from you.)
Why you should not rely on GitHub's redirect service
Once you have decided to change the module path, you might be tempted to use the automatic redirection service of your VCS hosting provider. GitHub, for example, automatically redirects traffic of a renamed repository to the new name, but there is a pitfall: If, at some fine day, you create a new repository of the same name as the old one, all redirects to the renamed repository stop.
So better look for a pure-Go solution.
Four steps to rename a module
Here are steps I found to be sort of a common recommendation, and they aren't too complicated, although you'd probably wish for a simpler version (with support from the Go toolchain). (Note that I'm strictly looking at single-module repositories. Modules inside monorepos have a few more cases to consider.)
Here we go. Say you're on GitHub and want to rename your module from github.com/oldorg/oldrepo
to github.com/neworg/newrepo
. (It doesn't matter if you want to change the organization name, the repository name, or both.) Then do these steps:
- Copy the current repository over to the new path. This could be a fork on GitHub, or whatever mechanism your VCS or VCS hosting service provide.
- Update
go.mod
in the new repository. Change themodule
directive to the new path, which, in this example, ismodule github.com/neworg/newrepo
. - Deprecate the old module. Add a deprecation message to the
go.mod
file. This is a comment before themodule
directive (or after the directive, in the same line) starting with// Deprecated:
(see the subsection “Deprecation” under "module
directive" in the module reference for details). - Provide clear migration instructions. In the old module's documentation, describe the steps users of your module must take to migrate over to the new module.
Your module users would need to do these migration steps:
- Update their
go.mod
file to require the new module - Update all
import
statements in their code to use the new path - Run
go mod tidy
to let Go do the housekeeping.
After some weeks or months, you may consider archiving the GitHub repository (or doing an equivalent step, depending on your VCS hosting provider) to make the message even more clear.
In any case, don't skip Step 0. Could be a time saver.