Cargo.lock
The Cargo.lock file is an automatically generated lockfile that records the exact resolved version, source URL, and SHA-256 cryptographic checksum of every direct and transitive dependency in a package or workspace. While Cargo.toml specifies flexible version ranges (such as serde = "1.0"), Cargo.lock pins the exact snapshot (such as 1.0.218) so every machine and CI runner builds identical code.
Cargo.toml (Human-Authored Intent):
serde = "1.0" ---> Allows any >=1.0.0, <2.0.0
|
v (Resolved once by Cargo, then locked)
Cargo.lock (Machine-Generated Snapshot):
[[package]]
name = "serde"
version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
Anatomy of an Entry in Cargo.lock
Cargo.lock uses format version 4 in modern Rust (version = 4 at the top of the file) and contains a [[package]] block for each crate in the dependency graph:
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "itoa"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "my_app"
version = "0.1.0"
dependencies = [
"itoa",
]
Should Cargo.lock Be Committed to Version Control (git)?
Modern Cargo best practices (and the official Cargo documentation) recommend committing Cargo.lock to Git for all projects—both binary applications and libraries—because it gives all contributors and CI workflows deterministic, reproducible test runs.
| Package Type | Commit Cargo.lock to Git? |
How cargo publish / Consumers Treat Cargo.lock |
|---|---|---|
| Binaries, CLI Tools, Servers, Workspaces | Yes (Mandatory) | cargo install --locked and CI builds use Cargo.lock to reproduce the exact tested dependency graph. |
| Libraries | Yes (Recommended for CI) | Downstream crates depending on your library ignore your Cargo.lock and resolve against your Cargo.toml ranges, while your own repo's CI stays deterministic. |
Updating and Enforcing Cargo.lock
Never edit Cargo.lock by hand. Use Cargo commands to update or enforce the lockfile:
| Command | Behavior |
|---|---|
cargo update |
Updates all dependencies in Cargo.lock to the newest SemVer-compatible versions allowed by Cargo.toml. |
cargo update <crate> |
Updates only <crate> (and its required sub-dependencies) in Cargo.lock. |
cargo update <crate> --precise 1.0.210 |
Pins <crate> in Cargo.lock to the exact version 1.0.210. |
cargo build --locked / cargo test --locked |
Fails immediately if Cargo.lock is missing or out of sync with Cargo.toml (always use --locked in CI!). |
cargo build --frozen |
Combines --locked and --offline: forbids both lockfile modifications and network access. |
fn verify_sha256_hex_format(checksum: &str) -> bool {
checksum.len() == 64 && checksum.bytes().all(|b| b.is_ascii_hexdigit())
}
fn main() {
let sample_checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674";
println!(
"Checksum is valid 64-char SHA-256 hex: {}",
verify_sha256_hex_format(sample_checksum)
);
}
Checksum is valid 64-char SHA-256 hex: true