Skip to content
rusthacks.dev
Tooling

Git Ignore for Rust Projects and What to Commit Step by Step

What belongs in .gitignore for a Rust project, why Cargo.lock is committed for binaries, and what to keep out of the repository: target, secrets, editor files and local config.

2 min read
Summarize in AI
Flat illustration for the post “Git Ignore for Rust Projects and What to Commit Step by Step”, composed around tooling.

A new Rust repository is nearly self-cleaning: cargo new writes a .gitignore containing one line. The questions show up later, when a .env file appears, a teammate asks whether to commit the lock file, or the clone takes ten minutes because someone added target/. This post gives a .gitignore to start from and the reasoning for each entry. It belongs with the housekeeping in rustup explained.

Cargo 1.90.

A starting .gitignore

.gitignoreText
# build output
/target

# local configuration and secrets
.env
.env.*
!.env.example
*.pem
*.key

# editors and OS
.idea/
.vscode/*
!.vscode/settings.json
!.vscode/extensions.json
.DS_Store

# profiling and coverage output
flamegraph.svg
perf.data*
*.profraw

The leading slash in /target anchors it to the repository root, so a source folder named target somewhere deeper is not ignored. !.env.example keeps a template with fake values committed so newcomers know which variables exist.

Cargo.lock

The lock file lists every dependency with its exact version and checksum.

ProjectCommit it?Why
Binary or serviceyesthe build you test is the build you ship
Libraryyes, per current Cargo guidancereproducible CI and contributor builds; users of your crate ignore it
Workspaceone at the rootshared by all members

The old advice was "libraries do not commit the lock file". The Cargo team revised it, since the lock helps catch breakage on your own CI schedule. Update it deliberately with cargo update, in its own commit. A lock file also enables cargo audit to check the versions you actually use.

What else to commit

  • rust-toolchain.toml for a shared compiler version (toolchain pinning)
  • .cargo/config.toml for project-wide build settings, such as linker flags
  • rustfmt.toml, clippy.toml and the [lints] table in Cargo.toml
  • .sqlx/ if you use SQLx offline mode (offline mode)
  • deny.toml for dependency policy

What to keep out

  • Anything with a secret: .env, private keys, service account files, database dumps
  • Local overrides such as .cargo/config.toml under your home directory (that file lives outside the repo anyway)
  • Benchmarks' output directories and big generated artifacts

A secret already committed

Ignoring a file does not remove it from history. If a token was pushed, rotate it first, then rewrite history if you must. Assume the old value is public. Pre-commit scanners like gitleaks catch it earlier.

Large target directories in CI

Cache target/ in CI instead of committing it, with a restore key based on Cargo.lock; see caching Cargo builds in CI. The cargo new behavior and lock file guidance are in the Cargo book's FAQ on Cargo.lock.

Taggedgitignore
Share

Keep reading

Flat illustration for the post “Incident Response for Rust Services a Short Runbook”, composed around deploy.
DevOps

Incident Response for Rust Services a Short Runbook

A one-page runbook for when a Rust service misbehaves: stabilize first, check recent changes, read the four golden signals, find the failing dependency, and use the Rust-specific evidence: panics, memory, executor stalls.

4 min read
Flat illustration for the post “Debugging Async Backtraces and Task Dumps in Tokio”, composed around async.
Tooling

Debugging Async Backtraces and Task Dumps in Tokio

A hung async service has no useful thread backtrace. Tokio task dumps capture the await stack of every task. Enable tokio_unstable and taskdump, trigger a dump from a signal or endpoint, and read where each task is parked.

4 min read

Get new posts by email

We send one email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.