
.gitignore的正确写法:先搞懂规则再动手
很多人写.gitignore都是“抄别人的模板”,但抄错一个符号就没用。先帮你理清楚Git怎么读.gitignore——它是从上到下逐行匹配的,后面的规则会覆盖前面的;规则里的斜杠(/)很重要,代表目录还是文件;感叹号(!)是“否定规则”,用来取消前面的忽略。
比如我之前犯过一个低级错误:想忽略src下的tmp文件夹,一开始写的是“src/tmp”(没加斜杠),结果没效果——后来才知道,不加斜杠Git会认为是“文件”,加了斜杠(“src/tmp/”)才代表“目录”,Git才会忽略整个文件夹。再比如,你先写“.log”要忽略所有log文件,后面加“!error.log”,那error.log就不会被忽略,这就是否定规则的作用——但一定要把否定规则放在被否定的规则后面,不然没用。
我整理了几个最常用的规则示例,你直接抄就行,不用自己试错:
规则写法 | 含义 | 适用场景 |
---|---|---|
.log | 忽略所有.log后缀的文件 | Node.js、Java项目的日志文件 |
src/tmp/ | 忽略src目录下的tmp文件夹(加斜杠是关键) | 前端项目的临时编译目录 |
!error.log | 不忽略error.log(否定前面的.log规则) | 需要保留的错误日志文件 |
config/local. | 忽略config目录下所有local开头的文件(如local.ini、local.json) | 本地数据库配置、API密钥文件 |
/dist/ | 忽略所有层级的dist文件夹(代表任意目录) | Vue、React项目的打包目录 |
写规则时还有个小技巧:尽量具体,别太宽泛。比如不要直接写“tmp/”,不然会忽略项目里所有叫tmp的文件夹——如果有src/tmp和docs/tmp,你可能只想忽略src下的,那就写“src/tmp/”,精准匹配才不会误删。
解决.gitignore失效的3个高频坑:我踩过的雷你别踩
写完规则没效果?90%是踩了这几个坑,我一个一个给你讲怎么解决。
坑1:已跟踪的文件,改.gitignore没用
Git的核心逻辑是:只忽略“未跟踪”的文件(从来没add过、没commit过的文件)。如果某个文件已经被add到暂存区,甚至commit到仓库了,后来你把它加进.gitignore,Git还是会继续跟踪它——因为Git“记住”了这个文件的存在。
比如你之前把config.ini提交到仓库了,后来想忽略它,直接写“config.ini”没用,得做两步:
git rm cached config.ini
(把文件从暂存区删掉,但本地文件还在,不会删你电脑里的文件); 之后Git才会忽略config.ini。我去年帮设计部的同学调项目时,他就是没做这步,改了半天.gitignore还是能看到config.ini,执行这个命令后,立马就好了。
如果是文件夹,比如node_modules已经被add过了,就用git rm cached -r node_modules
(-r代表递归删除文件夹里的所有文件),然后commit——我之前做Vue项目时,一开始没写node_modules到.gitignore,提交的时候卡了10分钟,后来删了暂存区的node_modules,再提交就快多了。
坑2:全局.gitignore和局部冲突
你可能不知道,Git还有“全局.gitignore”——就是所有项目都通用的忽略规则,比如Mac的.DS_Store、Windows的Thumbs.db,很多人会把这些系统文件写在全局里。但如果局部项目的.gitignore里写了相反的规则,比如全局写了“.DS_Store”,局部写了“!.DS_Store”,那局部规则会覆盖全局的,这时候.DS_Store就不会被忽略。
怎么看自己的全局.gitignore路径?打开终端执行git config global core.excludesfile
,就能看到路径(比如Mac下可能是~/.gitignore_global)。打开这个文件,看看有没有和局部项目冲突的规则——比如你全局忽略了.node_modules,但局部项目想保留node_modules,就在局部.gitignore里写“!node_modules/”,就能覆盖全局规则。
坑3:规则顺序写反了
前面说过,Git是从上到下读规则的,后面的规则会覆盖前面的。比如你先写“!error.log”,再写“.log”,那“!error.log”就没用了——因为后面的“.log”覆盖了它,所有log文件都会被忽略。我之前犯过这个错,想保留error.log,结果把否定规则写在前面,导致所有log文件都被忽略了,后来把顺序调换过来(先写“.log”,再写“!error.log”),就对了。
让.gitignore更好用的3个进阶技巧
等你掌握了基础写法和避坑技巧,可以试试这些进阶方法,让你的.gitignore更简洁、更好维护。
技巧1:用通配符减少重复
比如你有一个多模块的Java项目,每个模块下都有tmp目录(module1/tmp、module2/tmp、module3/tmp),一开始你可能会写三行规则:“module1/tmp/”“module2/tmp/”“module3/tmp/”,但其实用“/tmp/”就行——“”代表任意层级的目录,所以“/tmp/”会忽略所有子目录里的tmp文件夹,一行顶三行。我之前做这个项目时,一开始写了5行tmp规则,后来改成一行,省了好多空间。
技巧2:加注释,别让 的自己猜
用“#”开头写注释,比如“# 忽略日志文件”“# 忽略本地配置”“# 保留error.log日志”,不然过了半个月,你自己都忘了为什么写这个规则。我之前的一个老项目,.gitignore里有一行“.bak”,后来想改的时候,想不起来是忽略备份文件,查了半天提交记录才明白——从那以后,我每次写规则都加注释,现在看老项目的.gitignore,一眼就知道每个规则是干什么的。
技巧3:用命令验证规则是否正确
写完规则,你可以用git check-ignore -v 文件名
来验证——比如你想看看config.ini有没有被忽略,执行git check-ignore -v config.ini
,如果输出里有你的.gitignore路径和对应的规则(比如“.gitignore:12:config.ini config.ini”),说明已经被忽略了;如果没输出,说明没匹配到规则,得重新检查写法。
我每次写完规则都会用这个命令查一下,避免写错符号或者顺序——比如上次我写“src/tmp”没加斜杠,用这个命令查,结果没输出,才知道漏了斜杠,加上之后就有输出了。
其实.gitignore不难,难的是搞懂Git的“跟踪逻辑”和“规则优先级”——Git不是黑盒子,它的每一步都有逻辑,你搞懂了,就能自己排查问题。如果你按这些方法试了,欢迎回来告诉我效果!比如你解决了哪个问题,或者遇到了新的坑,我帮你一起看看——毕竟踩坑多了,就变成经验了~
你有没有发现,不管做哪个项目,电脑总会自动冒出些烦人的系统文件?比如Mac的.DS_Store、Windows的Thumbs.db,这些文件既没用又占位置,还总出现在Git的变更列表里——其实Git早给你留了“偷懒”的办法:全局.gitignore。它就像个“通用垃圾筐”,所有项目里的系统文件都能往里装,写一次管所有项目,省得每个项目都要复制一遍相同的规则。想知道自己的全局.gitignore在哪?打开终端输一行git config global core.excludesfile
就行,比如我Mac上的路径是~/.gitignore_global,直接打开改,把那些系统文件加进去,以后不管开什么新项目,Git都会自动忽略它们。
但每个项目总有自己的“小脾气”啊——比如做Vue项目要忽略node_modules,做Java项目要忽略target编译目录,做前端组件库要忽略dist打包文件夹。这些肯定不能放全局里,不然所有项目都给你忽略了,搞不好还会删错重要文件。这时候就得用项目内的.gitignore,它像给当前项目单独开的“小垃圾筐”,只管这一个项目的事儿,其他项目完全不受影响。比如我最近做的React项目,就在根目录建了个.gitignore,专门写了/node_modules/
和/dist/
,这样提交代码时就不会把几百MB的依赖包带进去,速度快了好多。
那如果全局和项目内的规则“打架”了怎么办?比如我全局里写了.log
(所有.log文件都忽略),但当前项目刚好要保留error.log——这时候别慌,项目内的规则是“老大”,全局得听它的。你只要在项目的.gitignore里写!error.log
,就能把全局的规则顶掉,当前项目的error.log就不会被忽略了。我上周帮朋友调项目时就遇到这情况:他全局忽略了.log,结果项目里的error.log总被误删,加了个!error.log
之后,立马就恢复正常了——这就是局部规则“压过”全局的魔法。
再说个细节哦:全局.gitignore里的规则是“默认选项”,项目内的是“定制选项”。比如你全局忽略了所有临时文件,但某个项目里的tmp文件夹是有用的,那就在项目内写!tmp/
,Git就会“听”项目内的,保留这个tmp文件夹。反过来,如果全局没写,但项目里想忽略某个文件,直接写进去就行—— 项目内的.gitignore永远是“最终解释权”拥有者,比全局的管用。
为什么我修改了.gitignore,但之前提交过的文件还是被跟踪?
Git的.gitignore只对“未跟踪”文件有效(即从未add或commit过的文件)。如果文件已经被提交到仓库,即使后续加入.gitignore,Git仍会继续跟踪。解决方法是先执行git rm cached 文件名(删除暂存区的文件,本地文件保留),再commit这个修改,之后Git才会忽略该文件。
全局.gitignore和项目内的.gitignore有什么区别?
全局.gitignore是所有Git项目通用的忽略规则(比如系统文件.DS_Store、Thumbs.db),配置路径可通过git config global core.excludesfile查看;项目内的.gitignore仅对当前项目生效。若两者规则冲突,局部规则会覆盖全局规则(比如全局忽略.log,局部写!.log,则当前项目不会忽略.log文件)。
写.gitignore时,斜杠(/)什么时候需要加?
斜杠的作用是区分“目录”和“文件”:① 加/代表匹配目录(如src/tmp/表示忽略src下的tmp文件夹);② 不加/代表匹配文件或目录(如src/tmp会同时匹配src下的tmp文件和tmp目录)。若想精准忽略目录, 加/。
怎么验证.gitignore的规则是否生效?
可使用git check-ignore -v 文件名命令验证。若输出包含.gitignore的路径和对应规则(如“.gitignore:10:config.ini config.ini”),说明规则生效;若无输出,则规则未匹配到目标文件,需检查写法(如符号错误、顺序颠倒)。
否定规则(!)为什么有时候没用?
否定规则(!)需要放在被否定的规则之后才有效。比如想保留error.log但忽略其他.log文件,需先写.log(忽略所有.log),再写!error.log(保留error.log);若顺序颠倒(先写!error.log再写.log),则后面的*.log会覆盖否定规则,导致error.log仍被忽略。