Go

How do you release v2 of a module? Compare the "major branch" and "major subdirectory" strategies, and explain +incompatible.

Question 410HardGo 1.22 to 1.25

Major branch (the common choice): on main, or on a v2 branch, change the go.mod line to module example.com/lib/v2, update every internal import to the /v2 path, then tag v2.0.0. The code stays at the repo root.

Major subdirectory: copy the code into v2/ with its own go.mod (module example.com/lib/v2). This works with pre-module GOPATH tooling, but you now maintain two copies of the code.

# major-branch workflow
go mod edit -module example.com/lib/v2
# rewrite internal imports (gofmt -r, sed, or a tool such as gomajor)
git commit -am "v2: new module path"
git tag v2.0.0 && git push --tags

+incompatible: if a repo tagged v2.3.0 without any go.mod (a pre-module release), consumers see example.com/lib v2.3.0+incompatible. The go command accepts it under the v1 path but cannot enforce compatibility. When that project later adds a go.mod without /v2, any new v2+ tag is rejected (the module path lacks the major suffix), and once the v1 path has a tagged version with a go.mod, the go command stops choosing +incompatible versions for @latest and -u upgrades.

Interviewers look for this: update the module line and internal imports, consider keeping v1 maintained on a branch, and mark the old version with // Deprecated: in its go.mod to point users to the new one.

More on Modules, Packages & Tooling

All 36 Modules, Packages & Tooling questions