Idea: move cargo-generated gitignore into target directory

The build system Meson automatically generates a .gitignore file (containing simply *) for every created build directory. This automatically excludes the entire directory from git (git only tracks directories with at least one tracked file in it)

Cargo could do the same thing for the target directory. This would means the target directory would be excluded regardless of its name and location, and the output of cargo new could be just a tiny bit tidier (since the decision to no longer exclude Cargo.lock by default, the target directory is the only thing in the generated .gitignore anyway)

Also, currently cargo new inside of an existing git repository skips creating a git repository (good) but also skips creating a .gitignore in the new directory (bad), which means git will try to track its target directory (if you're not using a workspace, or choosing to work on the crate in the subdirectory directly)

11 Likes

What about cargo clean, which nukes target?

1 Like

It likely shouldn't be generated by cargo new but every time a target/ is created.

5 Likes

FYI this has come up before in instead of writing a `.gitignore` with `/target` -- output a `.gitignore` with `*` *inside* `target/` · Issue #11548 · rust-lang/cargo · GitHub

Edit: this post made the incorrect assumption that all .gitignore files must be commited to git :frowning:

old answer Hello, first time poster here at IRLO 😅

I think there is a problem with having a .gitignore file in target/

A .gitignore file needs to be commited, so git would track the file target/.gitignore.

Imagine you're an unexperienced developer that created a new rust project. You would do cargo run and then git add, git commit. Now you have target/.gitignore committed.

After a while you do cargo clean (or rm -rf target, orany other tool that removes target) - now you have an unstaged change in git for the removal of target/.gitignore.

I'm not sure special casing cargo clean to not remove target/.gitignore helps because of the alternative ways to delete target.

This is incorrect. The .gitignore file is included in *, and so gets ignored. Feel free to test this locally. Cargo simply needs to ensure the .gitignore file always exists if target/ does.

1 Like

Dang, makes sense :sweat_smile:

1 Like

This strategy does not ignore /target if it is a symlink.

cargo new doesn't create or use a symlink for target. If someone wants to customize their setup to use a symlink for target then IMO they should be responsible for updating their top-level .gitignore if they want.

2 Likes

But these 2 things (name and location of the target dir) are essentially stable, and might as well be called part of Cargo's API. I know that there are scripts out in the wild that quietly assume both are fixed.

In addition, plenty of projects that want to exclude files or subdirectores (eg auto-generated files) actually use that top-level .gitignore file. So if this change went through, all of such projects that are greenfielded after this change would just have to do the work of creating one manually again (I assume nothing changes for existing projects). It's not a lot of added work but it's an additional wart where currently there is none.

1 Like

Surprisingly not that many. I've been using a customized build.target-dir for years and have barely noticed any failures.

1 Like

While git is dominant, it is not the only version control system, how will this idea work with those? Should cargo detect which one is in use and use an appropriate one? What about version control systems that can track empty directories (didn't svn allow this? It has been decades since I used it, so I could be wrong).

1 Like

I don't think the existence of other version control systems is motivation against adding .gitignore. The linked issue has a couple more examples of version control systems that might be reasonable to add as well, but .gitignore covers the 99% and gives ignore files for those systems a simple path forward.

That doesn't help across the ecosystem though.

FWIW, I have different directories for ale and tarpaulin to avoid clobbering directories and locked build directories. Coordinating all of them to point to the same place is far easier with symlinks than with per-project settings (that can easily end up as local diffs that cannot be ignored if there are other reasons for the configuration file to exist).