The replace Directive in go.mod
Use replace in go.mod to point a dependency at a local folder or a fork, when to use it, and why it does not apply to modules that depend on yours.
Sometimes you need a dependency to come from somewhere other than its normal location: a local copy you are fixing, or a fork with a patch the original has not merged yet. The replace directive in go.mod does that.
Pointing a Module at a Local Folder
Say your app uses example.com/mathx, and you have a local clone at ../mathx with a fix in progress:
go mod edit -replace example.com/mathx=../mathx
go.mod now contains:
replace example.com/mathx => ../mathx
Builds use the code in ../mathx instead of downloading it. The local folder must exist and contain its own go.mod with the matching module path. A wrong path fails with example.com/mathx@v0.0.0: replacement directory ../mathx does not exist.
If the module has never been published, you also need a require line. go mod edit -require example.com/mathx@v0.0.0 adds a placeholder version, which the replace then points at the folder.
Pointing a Module at a Fork
replace github.com/original/lib => github.com/yourname/lib v1.4.1-fix.1
The right side is a different module path plus a version. Your code keeps importing github.com/original/lib. Only the source changes. This is useful while waiting for a fix to be merged upstream.
Removing a Replacement
go mod edit -dropreplace example.com/mathx
go mod tidy
Do not commit local path replaces by accident:
A replace pointing at ../mathx only works on machines that have that folder in the same place. CI and teammates get build failures. For local development across several modules, prefer a go.work file, which stays out of go.mod and is usually not committed.
replace Only Applies to the Main Module
replace directives only take effect in the module you are building. If someone else depends on your module, your replace lines are ignored for them. This keeps a library from silently changing what its users download, but it also means you cannot ship a fix to users through replace. They would need their own.
Using replace to fix a module path mismatch:
Errors like module declares its path as: github.com/new/name but was required as: github.com/old/name mean a repository was renamed or forked. The proper fix is to change imports to the new path. A replace can paper over it temporarily.
When replace is the right tool:
A short-lived replace to a fork with a version, documented in the commit message and removed once upstream publishes the fix, is a good use. For editing several local modules together, use workspaces instead.
Summary
replace in go.mod points a dependency at a local folder or another module path and version. Local folders must contain their own go.mod. Replacements only apply when building your own module, local-path replaces break other machines if committed, and go.work is the better tool for working across several local modules.