0、背景
在软件开发过程中,我们使用Git进行版本控制时,经常会遇到一些不需要纳入版本管理的文件。这些文件可能包括:操作系统自动生成的临时文件、编辑器或IDE的配置文件(.vs)、编译生成的二进制文件和日志文件、包含敏感信息的配置文件(如API密钥、数据库密码)。如何没有配置.gitignore,这些文件会被提交到仓库中,造成以下问题:仓库体积无谓增大、克隆和拉取速度变慢、可能泄露敏感信息、团队成员间可能因本地配置文件产生冲突、污染提交历史,降低代码审查效率。
1、.gitgnore是什么
.gitignore是一个纯文本文件,用于指定Git应该忽略哪些文件或目录。它包含一系列模式匹配规则,Git会根据这些规则决定哪些文件不被跟踪。.gitgnore文件的不同存放位置表示不同级别的忽略规则,它可以存放在如下位置:
- 项目根目录的.gitignore:这是最常见的位置,作用于整个项目
- 子目录中的.gitignore:只作用于该目录及其子目录
- 全局.gitignore(通过git config --global core.excludesfile配置):作用于用户的所有Git项目
2、.gitgnore语法详解
2.1、基本匹配规则
- 空行:被忽略,可用于提高可读性
- #开头的行:注释
- 标准glob模式:shell使用的简化正则表达式
- 以/结尾:指定目录而非文件
- !开头:否定模式,取消忽略
2.2、通配符规则
- *:匹配任意数量字符(除了/),ex: (*.log:忽略所有.log文件)
- ?:匹配单个字符,ex: (?.tmp:忽略a.tmp,b.tmp等)
- []:字符范围,ex: ([abc].txt:忽略a.txt,b.txt,c.txt; [0-9].txt:忽略0.txt到9.txt)
- **:匹配任意层目录,ex: ( /temp:忽略所有目录下的temp文件/目录; a//b:忽略a/b,a/x/b,a/x/y/b等)
2.3、目录与文件区分
- 以/结尾表示目录,ex: (build/:忽略build目录及其内容)
- 不以/结尾表示文件和目录,ex: (build:忽略build文件和build目录)
2.4、否定规则
使用!前缀可以取消忽略:
*.log
!important.log
这将忽略所有.log文件,但保留important.log。注意:否定规则的顺序很重要,后面的规则会覆盖前面的。
3、高级用法
3.1、处理已跟踪的文件
如果文件已经被Git跟踪,再添加到.gitignore不会自动停止跟踪。需要先取消跟踪:
git rm --cached 文件名
对于目录:
git rm -r --cached 目录名
3.2、git check-ignore命令
用于检查为什么某个文件被忽略:
git check-ignore -v <file>
输出显示匹配的忽略规则及其位置。
3.3、调试.gitignore问题
当.gitignore不按预期工作时:
- 检查规则语法是否正确
- 确认文件未被Git跟踪(使用git ls-files)
- 使用git check-ignore调试
- 检查是否有更高优先级的规则覆盖
4、常见使用场景以及一个C++例子
4.1、忽略除特定文件外的所有文件
*
!.gitignore
!src/
!README.md
4.2、忽略目录但不忽略其内容
*
logs/*
!logs/.keep
4.3、一个C++项目中.gitignore示例
################
# 编译输出
################
*.o
*.obj
# ...其他编译输出...
################
# 构建系统
################
# CMake
CMakeCache.txt
CMakeFiles/
# ...其他CMake文件...
################
# IDE配置
################
.vs/
.idea/
# ...其他IDE文件...
################
# 测试框架
################
CTestTestfile.cmake
Testing/
# ...其他测试文件...
5、总结
配置良好的.gitignore文件可以:保持仓库清洁,只包含必要的源文件; 避免不同开发者间的构建系统冲突; 提高Git操作效率,减少不必要的文件跟踪; 保护敏感信息不被意外提交。建议在项目初始化时就创建完善的.gitignore文件,并随着项目发展不断维护更新。