How to Update All Modules Using Go Mod After Dependency Changes
Run go mod tidy after any dependency change to automatically add missing requirements, remove unused ones, and ensure your entire module graph stays consistent and reproducible.
When you modify dependencies in a Go project—whether through go get, go mod edit, or manual edits to go.mod—the rest of your module graph can drift into an inconsistent state. According to the golang/go source code, the canonical way to update all modules and restore consistency is the go mod tidy command. This tool scans your entire codebase, reconciles version constraints, and produces a minimal, reproducible build list.
Why go mod tidy Is Essential for Module Consistency
The Go toolchain does not automatically propagate dependency changes to the rest of your module graph. When you upgrade one library, transitive dependencies might need version bumps, or old requirements might become obsolete. Without cleanup, your go.mod and go.sum files accumulate unused entries and version conflicts that break reproducible builds.
go mod tidy solves this by performing two atomic operations:
- Adding missing requirements: It scans every package (including tests) and adds any imported module not already listed in
go.mod, selecting the minimal version that satisfies the import path. - Removing unused requirements: It drops entries from
go.modandgo.sumthat are no longer needed to build the module or its tests.
How go mod tidy Works Under the Hood
The implementation relies on a sophisticated graph-editing algorithm that lives in the Go toolchain source tree.
Command-Line Interface and Flag Handling
The entry point is implemented in src/cmd/go/internal/modcmd/tidy.go. The runTidy function registers flags such as -e, -v, -diff, -go, and -compat (lines 22–78), then initializes a fresh module loader state. It forces module mode with ForceUseModules = true and prepares to load the complete package tree.
Loading the Complete Package Graph
In src/cmd/go/internal/modload/load.go, the command invokes LoadPackages with the Tidy: true option. This loads all packages in the module—including test dependencies—to build a comprehensive graph of requirements. The loader constructs a ModuleGraph that represents every direct and transitive dependency with their version constraints.
Editing Requirements and Resolving Conflicts
The core logic resides in src/cmd/go/internal/modload/edit.go inside the editRequirements function (lines 23–50). This algorithm:
- Merges the must-select set (explicit versions from the command line or
go.mod) with try-upgrade candidates. - Determines the pruning mode (pruned vs. unpruned) based on the Go version directive.
- Constructs a selectedRoot map that records the target version for each root module.
- Repeatedly expands the graph using
extendGraphand walks it with a disqualification tracker (dqTracker) to locate version conflicts. - Downgrades or upgrades roots until the graph is internally consistent.
After resolution, the edited Requirements object is written back to go.mod, and go.sum is updated with the exact cryptographic hashes needed for reproducible builds.
Step-by-Step Workflow to Synchronize Dependencies
Use this sequence after updating any dependency to ensure your entire module graph stays synchronized:
# 1. Upgrade specific dependencies or all dependencies
go get -u ./... # Update all direct and indirect dependencies
# OR target a specific version
go get example.com/module@v1.4.2
# 2. Synchronize the entire module graph
go mod tidy # Adds missing deps, removes unused ones
# 3. (Optional) Preview changes without applying them
go mod tidy -diff # Shows unified diff of go.mod and go.sum
# 4. Verify the changes
git diff go.mod go.sum # Review before committing
Running go mod tidy is idempotent and efficient. The command reuses the module cache ($GOPATH/pkg/mod) and only contacts the proxy for modules whose sums are missing from go.sum.
Optional Flags for CI and Legacy Compatibility
When automating dependency updates, several flags control go mod tidy behavior:
-e: Continue processing even if some packages fail to load. Essential for large monorepos where temporary build breaks occur.-v: Verbose output that prints each module added, upgraded, or removed.-diff: Displays a unified diff of changes without modifyinggo.modorgo.sum. Ideal for CI checks that enforce manual review.-go=VERSION: Forces thegodirective ingo.modto a specific version, affecting module graph pruning behavior.-compat=VERSION: Ensures the resulting graph remains compatible with older Go toolchains, preventing the use of newer module graph features.
Summary
go mod tidyis the authoritative command to update all modules and ensure consistency after any dependency change.- The command lives in
src/cmd/go/internal/modcmd/tidy.goand orchestrates the module loader insrc/cmd/go/internal/modload/load.go. - The resolution algorithm in
src/cmd/go/internal/modload/edit.gohandles version conflicts viaeditRequirementsand a disqualification tracker. - Always run
go mod tidyaftergo getor manualgo.modedits to prune unused requirements and add missing transitive dependencies. - Use
-diffin CI pipelines to validate dependency changes without applying them, and-compatto maintain backward compatibility.
Frequently Asked Questions
What's the difference between go get and go mod tidy?
go get updates specific dependencies to requested versions but does not clean up the module graph. go mod tidy synchronizes the entire graph by adding missing requirements and removing unused ones. You should run go mod tidy after go get to ensure consistency.
Can I run go mod tidy in CI pipelines?
Yes, but use the -diff flag for validation checks without modifying files. If you want CI to auto-fix dependencies, run go mod tidy followed by go mod verify to ensure cryptographic sums match downloaded modules. The -e flag helps CI continue even if some packages are temporarily broken.
Why does go mod tidy remove lines from my go.mod?
The command removes unused requirements—dependencies that no package in your module (including tests) actually imports. This keeps go.mod minimal and prevents bloat from old transitive dependencies that are no longer referenced in the code.
Is it safe to run go mod tidy automatically before every build?
Generally yes, but be cautious in multi-module repositories or when working with legacy code. The -compat flag ensures you do not accidentally adopt module graph features incompatible with older Go versions. For production builds, commit the resulting go.mod and go.sum changes to version control rather than running tidy dynamically.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →