为什么文件名已经 add 到 .gitignore 文件了,为什么没有生效呢???这个破问题基本是遇到一次查一次,索性研究一下,把神经元突兀刺激下。
.gitignore不生效可能的几种常见原因分析:
1、文件已经被 Git 跟踪了
.gitignore只对未被 Git 跟踪的文件生效。如果文件已经加入过版本控制,即使后来添加到.gitignore中,Git仍会继续跟踪它。这种是最最常见的场景。解决办法是:
git rm --cached <文件或目录>
比如根目录下的 logs 文件、.mvn 等文件夹
git rm --cached -r logs/
git rm --cached -r .mvn/
也可以针对单个文件进行操作,如 mvnw、mvnw.cmd
git rm --cached mvnw
git rm --cached mvnw.cmd
然后再提交:
git commit -m "Remove tracked file so .gitignore can take effect" git 中文件的生命周期(状态)
这里补充解释下Git 中文件的生命周期(状态),看下表:
三个区域:工作区 / 暂存区 / 仓库
理解 Git 跟踪状态最直观的方法是理解这三层结构:
+----------------+
| 仓库区(HEAD) |
+----------------+
git commit
+----------------+
| 暂存区(Index) |
+----------------+
git add
+----------------+
| 工作区(Working Dir) |
+----------------+
• 工作区:你正在编辑的文件。
• 暂存区:你用git add暂存的改动。
• 仓库区(HEAD):你用git commit提交后的内容。
状态转移
+-----------------+ git checkout <f> +-------------+
| Untracked |<-------------------------| Workspace | (represented by )
| (Implicit Start)| |(Working Dir)|
+-----------------+-------------------------> +-------------+
| | ^ | 修改 (modify)
| git add <f> | | |
v | | v
+-----------------+ git commit -a +-------------+
| Committed-1 |------------------------->| Staged |
| (Previous HEAD) | |(Index) |
+-----------------+<--------------------------+-------------+
^ | 修改 (modify) ^ | git commit
| | | |
| v | v
+-----------------+ +-----------------+
| Modified |<------- git stage <f> ------| Committed-2 |
| (Working Dir) | | (New HEAD) |
+-----------------+-------------------------> +-----------------+
^ | git checkout <f> ^ |
| | (discard changes) | | git reset HEAD^ --soft
| +------------------------------------+ |
| |
+------------------ git reset <f> ------------------+
(unstage)
Committed-1 <--- git reset HEAD^ --mix (default) --- Staged
Committed-1 <--- git reset HEAD^ --hard --- Modified / Staged / Workspace (discards all changes)
--------------------------------------------------------------------
(1) git revert HEAD (creates a new commit that undoes changes from HEAD, points to Committed-1 or previous state)
(2) git revert HEAD (same as above, illustrated as alternative path)
--------------------------------------------------------------------2、.gitignore 文件语法有误
• 忽略目录要加/结尾,例如:logs/
• 忽略所有.log文件:*.log
• 忽略某目录下的所有文件:dir/**
例如:
# 忽略目录
build/
logs/
# 忽略所有 .log 文件
*.log
# 忽略临时文件
*.tmp3、路径不匹配
.gitignore是相对项目根目录(即.git所在目录,注意.git一般是隐藏目录)写的。如果你在子目录中创建.gitignore,路径会相对于这个子目录。可以使用下面命令检查具体某个文件是否被忽略:
git check-ignore -v <文件路径>
例如
> git check-ignore -v .mvn # 检查.mvn
> .gitignore:40:/.mvn/ .mvn # 返回结果
上述基本涵盖常见的场景,有些特殊情况如 有多个 .gitignore 文件冲突或覆盖、全局.gitignore文件干扰 等也会影响,但不常见,如果上述未能解决,则可以按照这两个进行排查。但是更为直接的是强制重新让.gitignore生效
4、强制重新让 .gitignore 生效
*强制重新让.gitignore生效是通过重新缓存整个项目来实现,这种情况一般适合在本地测试时使用。具体如下:
git rm -r --cached .
git add .
git commit -m "Re-apply .gitignore rules"
这个命令会从 Git 索引(暂存区)中移除当前所有被跟踪的文件,但不会删除工作区中的实际文件。换句话说就是:
• 本地磁盘上的文件还在,不会丢失。
• Git 会认为这些文件“被删除了”,并会在下一次git commit中记录这些变化(作为删除操作)。
• 如果你把这个 commit 推送到远程仓库,其他人 pull 下来时,会看到这些文件被删除。
假如你运行了
git rm -r --cached .
git add .
git commit -m "Re-apply .gitignore rules"
你.gitignore了build/,这时:
1. 所有当前被 Git 跟踪的文件都会被标记为删除。
2..gitignore生效后,像build/这种你希望忽略的目录就不会被重新add回来。
3. 其他所有未被.gitignore忽略的文件会重新被add。
最终,你的commit实际上就是:
• 删除了build/(或其它被.gitignore的文件);
• 又重新add了其他所有文件;
• 所以git log 会出现一个「大变动」的commit。
这种操作会造成大量 Git 历史变动,文件删除再重新添加会让Git历史显得很杂乱,不必要地增加版本库负担。
5、场景对比参考
6、 常用命令回顾
领取专属 10元无门槛券
私享最新 技术干货