How to rename or relocate a public Go module

Import paths should remain stable. But what if you need to rename or relocate a public repository that others rely on?

For instance, you have this module:

github.com/myorg/mymodule

and you want to move this module to:

gitlab.com/otherorg/mymodule

The solution: Don't move it. Copy it. (Via fork or otherwise).

The point is that all clients cannot upgrade to the new path at the same time. There will always be clients that continue using the old module for a while.

So copy the module over to the new path but don't touch the original module. Or rather, update the README with a deprecation note, and consider marking the module as deprecated. ( The “Deprecation” subsection in the Go mod reference shows how to do this.)

Tip: Use canonical import paths

Did I say don't move the module? Well, there is an option for that, too:

Canonical import paths, a.k.a. vanity import paths.

However, this option requires planning in advance. A canonical import path can be different from the repository URL. The go get command (and related commands) retrieve the final repository location by sending a specifically crafted HTTP GET to the server that the canonical path points to.

The full process is described here, but as a quick example, let's take a look at my what module, a package for adding ad-hoc logging code.

The canonical import path is appliedgo.net/what. The go command queries that URL for a pointer to the true repo. The page appliedgo.net/what contains a Meta tag that points to github.com/appliedgocode/what (plus information about the brand of the version control system), where the go command then can download the module.

(If you are curious, open appliedgo.net/what, open the browser tools, and search the HTML head for go-import. You will find this Meta tag: <meta name="go-import" content="appliedgo.net/what git https://github.com/appliedgocode/what">.)

With this canonical import path in place, if I ever want to move the module to another repository, I would simply update the Meta tag at appliedgo.net/what.

Easy-peasy. And appliedgo.net/what is so much more elegant and easier to memorize than github.com/appliedgocode/what.