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.mod and go.sum that 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:

  1. Merges the must-select set (explicit versions from the command line or go.mod) with try-upgrade candidates.
  2. Determines the pruning mode (pruned vs. unpruned) based on the Go version directive.
  3. Constructs a selectedRoot map that records the target version for each root module.
  4. Repeatedly expands the graph using extendGraph and walks it with a disqualification tracker (dqTracker) to locate version conflicts.
  5. 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 modifying go.mod or go.sum. Ideal for CI checks that enforce manual review.
  • -go=VERSION: Forces the go directive in go.mod to 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 tidy is the authoritative command to update all modules and ensure consistency after any dependency change.
  • The command lives in src/cmd/go/internal/modcmd/tidy.go and orchestrates the module loader in src/cmd/go/internal/modload/load.go.
  • The resolution algorithm in src/cmd/go/internal/modload/edit.go handles version conflicts via editRequirements and a disqualification tracker.
  • Always run go mod tidy after go get or manual go.mod edits to prune unused requirements and add missing transitive dependencies.
  • Use -diff in CI pipelines to validate dependency changes without applying them, and -compat to 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →