我的 .gitignore 文件包含一堆 Rust 代码:
# Generated by Cargo
# will have compiled files and executables
*/target/
*/target/*
# Performance stuff
**/*.data
**/*.data.old
**/*.svg
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
下面是许多 Rust 项目,但它们都不包含其他 git 内容:
$ find . -name .git
./.git
$ find . -name .gitignore
./.gitignore
最近的更改包括一些程序宏的嵌套 Rust 项目 - 所以我的文件树看起来像
|.gitignore
|<other projects>
|OneProject/
|--<other files>
|--NestedProject
|---- <other files>
|---- target/
|------ <lots of unwanted stuff getting added>
我注意到(在推送过程中)它从嵌套项目的目标目录中添加了大量内容。 (当时,我的 .gitignore 只有
*/target/
- 之后添加了额外的 */target/*
。
我做了一个本地
git reset HEAD~1
,将.gitignore
文件修改为现在的样子,并尝试再次添加,但文件仍然显示为已添加。我做了 git reset
,然后切换到一个新分支(我不想出于一般的怯懦而强制推出),并尝试按照 Git Ignores 和 Maven 目标 的说明进行操作 - 即:
git rm -rf --cached .
git add .
git commit -m "gitignore is now working"
git push
OneProject/NestedProject/target/
下的项目仍然被推送(通过浏览器确认)。
我错过了什么?
*/target/
不起作用的原因是路径开头的分隔符相对于 gitignore 的文件夹匹配,而单个星号仅匹配单个文件夹级别。正如 gitignore 文档在模式格式部分中所述:
如果模式的开头或中间(或两者)有分隔符,则该模式相对于特定 .gitignore 文件本身的目录级别。
这意味着,如果您的目标文件夹位于
OneProject
下,则排除 */target/
将会起作用,因为目标位于相对于 gitignore 文件夹的一级子文件夹级别下。
如果您的目标文件夹始终位于 gitignore 文件夹下方几级,您可以将
*/target/
替换为 */*/target/
并删除 */target/*
。
相反,斜杠前面的前导双星号会匹配工作目录的all目录,这就是为什么这种写法也有效。如果您的目标文件夹将来可能会移动到其他地方,或者您计划拥有其他目标文件夹并且所有这些文件夹都必须被忽略,则此解决方案可能更可行。
前导“”后跟斜杠表示在所有目录中匹配。例如,“/foo”在任何地方匹配文件或目录“foo”,与模式“foo”相同。 “**/foo/bar”匹配直接位于目录“foo”下的任何位置的文件或目录“bar”。