项目的常用配置文件
这里考虑的是使用 git 进行版本控制的跨平台项目,主要考虑普通文本以及 C++项目中需要的配置文件。 下文包括这些配置文件的基本介绍以及模板。
.editorconfig
通过 .editconfig
,我们可以实现跨平台,跨 IDE
的文本统一控制,常见的设置包括
tab,文本编码,换行符等。很多代码编辑器和IDE都支持
.editconfig
:VS 直接支持,VScode
需要使用官方插件来提供支持。
某些文件对格式是非常敏感的,我们需要对此进行专门设置:
Makefile
必须使用 tab,不能使用空格替代!- bat 脚本,pwsh 脚本以及 VS 配置文件这些与windows平台深度绑定的,建议使用 CRLF 换行符,否则可能导致异常
- markdown 文件允许结尾的空格
- 对数据文件不允许更改换行符
- 对 build 文件夹,out 文件夹和 data 文件夹的内容撤销所有设置
为了达到上述要求,对应的.editconfig
文件示例如下
1 | # fenglielie@qq.com |
说明:
- 使用
root = true
表明这是最终的.editconfig
文件,否则还可能尝试从父目录中寻找,默认会递归向上查找,即使存放位置在项目文件夹之外,可以在 windows 的每个盘符根目录下放置一份即可 - 这里首先使用
[*]
匹配所有文件进行设置,后面对具体的文件进行单独设置 #
开头的为注释行,空行和注释行都会被忽略- 两个规则冲突时,后文的匹配规则会覆盖前文中的规则
.gitattributes
我们希望使用这个配置文件解决什么问题呢:主要是 git 把哪些文件视作文本文件,哪些视作二进制文件,这涉及到 git 的差异比较和合并,以及换行符的处理,参考官方文档
这里提供一个参考的.gitattributes
文件,主要是在 Git
中适配前面的.editconfig
文件
1 | # 对所有 .bat, .cmd 文件强制使用 CRLF |
.clang-tidy
clang-tidy 可以提供 C++的静态语法检查,包括很多具体规则的检查,可以使用如下的注释去关闭特定位置的特定检查
1 | 关闭当前行的所有检查 // NOLINT |
clang-tidy 模板如下
1 | # fenglielie@qq.com |
.clang-format
clang-format 可以提供 C++的语法格式化。
clang-format 模板如下
1 | --- |
.clangd
clangd有时候比较蠢,我们可以通过在项目根目录添加.clang文件来提示它,例如它很可能在windows上找不到正确的标准库头文件,而是会跳转到MSVC的标准库头文件,我们可以添加--include-directory=
来指定。
例如 1
2
3
4
5
6
7
8CompileFlags:
Add:
- '-Wall'
- '-Wextra'
- '-Wshadow'
- '-Wno-unused-parameter'
- '-std=c++17'
- '--include-directory=/path/to/compiler/include'
有时候需要使用C语言项目,但是默认的配置是针对C++的,对于C语言目前使用下面的配置
1
2
3
4
5
6
7CompileFlags:
Remove: [-std=*]
Add: [-xc, -Wall]
Compiler: clang
Diagnostics:
ClangTidy:
Remove: readability-identifier-naming
除此之外,clangd主要会基于compile_commands.json
文件进行代码提示,CMake项目可以用特定选项在build/
中自动生成compile_commands.json
。
.gitconfig
Git 的用户级配置参考
1 | [user] |
.gitignore
语法规则参考官方文档
基本语法
- 空行被直接忽略
- 以#开头的行视为注释,不能让注释出现在规则之后,以下语法可能有错误
1 | *.log # 所有日志文件 |
- 其余每行表示一个 pattern,行尾的空格被忽略
- !意味着取反,即原本被匹配上的文件被忽略,加上!后这些文件则被包含进来,但是这里需要保证它的各级父目录没有被忽略,否则仍然无法包含
- pattern 严格区分大小写
- pattern
含有特殊字符例如
#
,!
时需要使用转义,例如\!
,\#
- pattern
视
/
为路径分隔符,是否含有/
对匹配规则影响很大
在 pattern
不含有/
时,执行如下的简单规则:(匹配当前位置和所有子文件夹的所有文件和文件夹)
- 星号(
*
)匹配零个或多个任意字符,不包括/
; - 问号(
?
)只匹配一个任意字符,不包括/
; - [
abc
]匹配任何一个列在方括号中的字符(要么匹配一个 a,要么匹配一个 b,要么匹配一个 c); - 如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如
[
0-9
] 表示匹配所有 0 到 9 的数字);
在简单规则下,我们不需要考虑路径问题,只需要关注文件名和文件夹名自身的匹配,因为规则会遍历所有子文件夹。
简单规则示例:
1 | # 忽略所有以 ~ 结尾的文件(通常是临时文件) |
在 pattern
含有/
时,匹配规则会考虑路径问题,更加复杂:
- 如果在 pattern
的开头或者中部出现
/
,则只会匹配相对于.gitignore 文件所在位置的相对路径,例如/doc/test
和doc/test
效果一样 - 如果在 pattern
的结尾出现
/
,则只会匹配到文件夹,不会匹配任何文件
使用**
和/
结合还有如下的特殊规则,以满足复杂规则下的需求:
- 例如
**/foo
可以匹配任何位置的 foo 文件或文件夹,效果和foo
一样 - 例如
**/foo/bar
可以匹配任意位置下的 bar 文件或文件夹,但是要求它的父文件夹为 foo - 例如
/**
匹配当前位置下的所有项,abc/**
匹配当前位置的子文件夹 abc 下的所有项 - 例如
a/**/b
可以匹配任意个中间目录,还可以没有中间目录,包括a/b
,a/x/b
和a/x/y/b
等 - 在其它情形,即
**
不直接和/
相邻时,效果同*
复杂规则示例
1 | # 忽略build目录自身(也忽略了它的所有子项) |
白名单模式
我们可以先忽略一般项,再添加特殊项
1 | # 忽略所有 .txt 文件 |
注意这里build/*
和build/
效果是不一样的,前者才支持重新添加
build 中的某些文件。
我们还可以先排除所有,然后根据需要添加指定的项,仍然需要注意:添加的项的父目录也需要未被排除
1 | # 忽略一切 |
对于当前目录下以点开头的文件(通常为配置脚本)我们希望默认包含,对于以点开头的文件夹则希望默认排除,可以使用如下设置
1 | /.*/ |
规则优先级
Git 检查忽略规则的时候有多个来源,它的优先级如下(由高到低):
- 从命令行中读取可用的忽略规则
- 当前目录定义的
.gitignore
规则 - 父级目录定义的
.gitignore
规则,依次递推 $GIT_DIR/info/exclude
文件中定义的规则core.excludesfile
中定义的全局规则
模板
Github 官方提供了很多模板,参考gitignore 模板。
下面给自己准备几个模板吧,涉及的主要是 C++ 和 LaTeX。
C/C++ 项目模板
1 | # [[C++]] |
LaTeX 项目模板(这里选择白名单模式,因为LaTeX项目可能产生很多杂项文件)
1 | * |