Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(faq): Recommend always committing Cargo.lock #12275

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions src/cargo/ops/cargo_new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ struct MkOptions<'a> {
path: &'a Path,
name: &'a str,
source_files: Vec<SourceFileInformation>,
bin: bool,
edition: Option<&'a str>,
registry: Option<&'a str>,
}
Expand Down Expand Up @@ -447,7 +446,6 @@ pub fn new(opts: &NewOptions, config: &Config) -> CargoResult<()> {
path,
name,
source_files: vec![plan_new_source_file(opts.kind.is_bin(), name.to_string())],
bin: is_bin,
edition: opts.edition.as_deref(),
registry: opts.registry.as_deref(),
};
Expand Down Expand Up @@ -552,7 +550,6 @@ pub fn init(opts: &NewOptions, config: &Config) -> CargoResult<NewProjectKind> {
version_control,
path,
name,
bin: has_bin,
source_files: src_paths_types,
edition: opts.edition.as_deref(),
registry: opts.registry.as_deref(),
Expand Down Expand Up @@ -744,9 +741,6 @@ fn mk(config: &Config, opts: &MkOptions<'_>) -> CargoResult<()> {
// for all mutually-incompatible VCS in terms of syntax are in sync.
let mut ignore = IgnoreList::new();
ignore.push("/target", "^target$", "target");
if !opts.bin {
ignore.push("/Cargo.lock", "^Cargo.lock$", "Cargo.lock");
}

let vcs = opts.version_control.unwrap_or_else(|| {
let in_existing_vcs = existing_vcs_repo(path.parent().unwrap_or(path), config.cwd());
Expand Down
40 changes: 20 additions & 20 deletions src/doc/src/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,33 +102,32 @@ issue][cargo-issues].

[cargo-issues]: https://github.com/rust-lang/cargo/issues

### Why do binaries have `Cargo.lock` in version control, but not libraries?
### Why should I always have `Cargo.lock` in version control?

The purpose of a `Cargo.lock` lockfile is to describe the state of the world at
the time of a successful build. Cargo uses the lockfile to provide
deterministic builds on different times and different systems, by ensuring that
the exact same dependencies and versions are used as when the `Cargo.lock` file
was originally generated.

This property is most desirable from applications and packages which are at the
very end of the dependency chain (binaries). As a result, it is recommended that
all binaries check in their `Cargo.lock`.

For libraries the situation is somewhat different. A library is not only used by
the library developers, but also any downstream consumers of the library. Users
dependent on the library will not inspect the library’s `Cargo.lock` (even if it
exists). This is precisely because a library should **not** be deterministically
recompiled for all users of the library.

If a library ends up being used transitively by several dependencies, it’s
likely that just a single copy of the library is desired (based on semver
compatibility). If Cargo used all of the dependencies' `Cargo.lock` files,
then multiple copies of the library could be used, and perhaps even a version
conflict.

In other words, libraries specify SemVer requirements for their dependencies but
cannot see the full picture. Only end products like binaries have a full
picture to decide what versions of dependencies should be used.
This property is desirable for all projects, whether they are intended to be used
as a library or from applications and packages which are at the very end of the
dependency chain (binaries). As a result, it is recommended that all projects
check in their `Cargo.lock`. This allows all users to clone a project and start
working on it risking unexpected dependency issues.

Note that a `Cargo.lock` in a library is only useful when developing it, it is
ignored when using the library as a dependency. It is however very useful when
developing. It ensures reproducible tests when going through the version history.
It also allows advanced users to inspect for library's `Cargo.lock` when facing
compatibility issues with dependencies. In particular, it allows reproducibility
across different environments such as a Continuous Integration (CI) server or the
workstations of all contributors.

It is recommended for all projects, and libraries in particular, to regularly
refresh their lockfile to detect compatibility issues with dependencies as soon
as possible. You can achieve it manually with [`cargo update`][cargo-update] or
with tools such as _Dependabot_.

### Can libraries use `*` as a version for their dependencies?

Expand Down Expand Up @@ -301,6 +300,7 @@ causes and provide diagnostic techniques to help you out there:
and `Cargo.toml` using a [custom merge tool].


[cargo-update]: ./commands/cargo-update.md
[links]: https://doc.rust-lang.org/cargo/reference/resolver.html#links
[conventions in place]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#-sys-packages
[`direct-minimal-versions`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#direct-minimal-versions
Expand Down
11 changes: 4 additions & 7 deletions src/doc/src/guide/cargo-toml-vs-cargo-lock.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,11 @@ about them, here’s a summary:
* `Cargo.lock` contains exact information about your dependencies. It is
maintained by Cargo and should not be manually edited.

If you’re building a non-end product, such as a rust library that other rust
[packages][def-package] will depend on, put `Cargo.lock` in your
`.gitignore`. If you’re building an end product, which are executable like
command-line tool or an application, or a system library with crate-type of
`staticlib` or `cdylib`, check `Cargo.lock` into `git`. If you're curious
Always check `Cargo.lock` into `git`. This advice applies to all projects:
libraries, command line tools, applications, etc. If you're curious
about why that is, see
["Why do binaries have `Cargo.lock` in version control, but not libraries?" in the
FAQ](../faq.md#why-do-binaries-have-cargolock-in-version-control-but-not-libraries).
["Why should I always have `Cargo.lock` in version control?" in the
FAQ](../faq.md#why-should-i-always-have-cargolock-in-version-control).

Let’s dig in a little bit more.

Expand Down
1 change: 0 additions & 1 deletion tests/testsuite/init/auto_git/out/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
/target
/Cargo.lock
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
target
Cargo.lock
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
target
Cargo.lock
1 change: 0 additions & 1 deletion tests/testsuite/init/git_autodetect/out/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
/target
/Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@
# Added by cargo

/target
/Cargo.lock
1 change: 0 additions & 1 deletion tests/testsuite/init/inferred_lib_with_git/out/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
/target
/Cargo.lock
1 change: 0 additions & 1 deletion tests/testsuite/init/mercurial_autodetect/out/.hgignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
^target$
^Cargo.lock$
1 change: 0 additions & 1 deletion tests/testsuite/init/pijul_autodetect/out/.ignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
/target
/Cargo.lock
1 change: 0 additions & 1 deletion tests/testsuite/init/simple_git/out/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
/target
/Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@
# already existing elements were commented out

#/target
/Cargo.lock
1 change: 0 additions & 1 deletion tests/testsuite/init/simple_hg/out/.hgignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
^target$
^Cargo.lock$
1 change: 0 additions & 1 deletion tests/testsuite/init/simple_hg_ignore_exists/out/.hgignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@
# Added by cargo

^target$
^Cargo.lock$
4 changes: 2 additions & 2 deletions tests/testsuite/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ fn simple_git() {

let fp = paths::root().join("foo/.gitignore");
let contents = fs::read_to_string(&fp).unwrap();
assert_eq!(contents, "/target\n/Cargo.lock\n",);
assert_eq!(contents, "/target\n",);

cargo_process("build").cwd(&paths::root().join("foo")).run();
}
Expand All @@ -112,7 +112,7 @@ fn simple_hg() {

let fp = paths::root().join("foo/.hgignore");
let contents = fs::read_to_string(&fp).unwrap();
assert_eq!(contents, "^target$\n^Cargo.lock$\n",);
assert_eq!(contents, "^target$\n",);

cargo_process("build").cwd(&paths::root().join("foo")).run();
}
Expand Down