Commit both the manifest and the file that records exact versions. That is go.mod for Go, Cargo.lock for Rust, the project file for .NET, composer.lock for PHP, Gemfile.lock for Ruby, and Package.resolved for Swift apps. A scanner needs those exact versions to match advisories accurately.
The table
| Ecosystem | File that matters most | Also read | Note |
|---|---|---|---|
| Go | go.mod | go.sum | go.sum is hashes, not a lockfile |
| Rust | Cargo.lock | Cargo.toml | Commit the lock for applications |
| .NET | Project file such as csproj | packages.config, nuspec | See our NuGet lock file post |
| PHP | composer.lock | composer.json | Libraries need not commit the lock |
| Ruby | Gemfile.lock | Gemfile, gemspec | Commit for apps and gems per Bundler docs |
| Swift | Package.resolved | Package.swift | Ignored when your package is a dependency |
| Java and Kotlin | pom.xml, or Gradle build files | Gradle lockfile if enabled | Check how your tool resolves Gradle |
The first columns follow the file names in GitHub's dependency graph reference, which lists go.mod for Go, Cargo.lock for Rust, composer.lock for Composer, Gemfile.lock for RubyGems, Package.resolved for Swift and pom.xml for Maven. That reference lists no recommended file for Gradle, and the page does not list Kotlin separately.
Why the lockfile matters
A manifest holds ranges. A lockfile holds the resolved result. Advisories are written against specific versions, so a scan that sees only ranges can only guess which version you run.
For the reasons behind each choice, see what a lockfile is and why to commit it.
Application or library
- Applications should commit the lock file so every build and every scan uses the same versions.
- Libraries have more discretion. Composer says it is not necessary, and SwiftPM says a library's Package.resolved does not pin anything for its users.
A short checklist
- List the build tools in your repository. Monorepos often have several.
- Confirm each one has its exact-version file committed.
- For Go, rely on go.mod and the module graph, since there is no lock file.
- For Gradle, decide whether to enable dependency locking or to scan the resolved graph from a build.
- Make sure CI fails if the lock file would change.
- Scan on every pull request and on a schedule.
Quick check
Do I need go.sum for scanning?
Scanners read go.mod and the module graph for versions. Keep go.sum committed for integrity checks.
My Swift project is a library. Should I still commit Package.resolved?
It is optional. It will not pin versions for your users, but it can keep your own CI consistent.
Safeguard's SBOM and dependency scanning builds an inventory from project files like these. Check a repository with the free scan.
Sources
- Dependency graph supported package ecosystems
- SwiftPM: Resolving and updating dependencies
- Composer basic usage
- Go Modules Reference
Last reviewed: 19 October 2026.