12 KiB
.gitignore
git add / git commit / git diff / git stash / .gitignore
✍️ 童仲毅 | ⏳ 2018 年 12 月 24 日
©️ 本文演绎自 Atlassian 编写的 Saving Changes。页面上所有内容采用知识共享-署名(CC BY 2.5 AU)许可协议。
Git 将工作副本中每个文件都视作以下三者之一:
- 被追踪的文件——之前被缓存或提交过的文件;
- 未被追踪的文件——尚未被缓存或提交过的文件;
- 被忽略的文件——Git 被明确告知要忽略的文件。
被忽略的通常是构建过程(build)和机器生成的文件。它们可以根据你的仓库源码生成,或者不应该被提交。下面是一些常见的栗子:
- 缓存的依赖文件,例如
/node_modules或/packages里的内容 - 编译后的代码,例如
.o、.pyc、.class - 构建输出的目录,例如
/bin、/out、/target - 运行时生成的文件,例如
.log、.lock、.tmp - 隐藏的系统文件,例如
.DS_Store、Thumbs.db - 个人的开发环境(IDE)配置文件,例如
.idea/workspace.xml
忽略的文件通过一个名为 .gitignore 的文件追踪,该文件位于仓库的根目录下。Git 没有显式的忽略命令。添加新文件时必须手动修改并提交 .gitignore 文件来添加忽略的文件。.gitignore 文件里的规则用于匹配文件名,从而判断该文件是否需要被忽略。
目录
- [Git 忽略文件的匹配规则](#Git 忽略文件的匹配规则)
- [仓库内的共享 .gitignore 文件](#仓库内的共享 .gitignore 文件)
- [个人的 Git 忽略规则](#个人的 Git 忽略规则)
- [全局的 Git 忽略规则](#全局的 Git 忽略规则)
- 忽略一个被提交过的文件
- 提交被忽略的文件
- 储存被忽略的文件
- [调试 .gitignore 文件](#调试 .gitignore 文件)
Git 忽略文件的匹配规则
.gitignore 使用 GLOB 规则 匹配文件名。你可以使用多种符号创建你的规则:
| 匹配规则 | 样例 | 解释* |
|---|---|---|
**/logs |
logs/debug.log logs/monday/foo.bar build/logs/debug.log |
在规则前接两个星号,从而在仓库任何位置匹配该目录。 |
**/logs/debug.log |
logs/debug.log build/logs/debug.log 但不会匹配 logs/build/debug.log |
使用两个星号匹配文件名和父目录名称。 |
*.log |
debug.log foo.log .log logs/debug.log |
单个星号为通配符,匹配零或多个字符。 |
*.log !important.log |
debug.log trace.log 但不会匹配 important.log logs/important.log |
在规则前接一个感叹号作为否定。如果文件同时符合一个先定义的规则和一个后定义的否定规则,它将不会被忽略。 |
*.log !important/*.log trace.* |
debug.log important/trace.log 但不会匹配 important/debug.log |
在否定规则后定义的规则会覆盖之前定义的否定规则。 |
/debug.log |
debug.log 但不会匹配 logs/debug.log |
前接斜杠只匹配仓库根目录下的文件。 |
debug.log |
debug.log logs/debug.log |
规则默认匹配任何目录下的文件。 |
debug?.log |
debug0.log debugg.log 但不会匹配 debug10.log |
一个问号用于匹配一个符号。 |
debug[0-9].log |
debug0.log debug1.log 但不会匹配 debug10.log |
方括号用于从特定范围中匹配单个字符。 |
debug[01].log |
debug0.log debug1.log 但不会匹配 debug2.log debug01.log |
方括号用于从特定集合中匹配单个字符。 |
debug[!01].log |
debug2.log 但不会匹配 debug0.log debug1.log debug01.log |
感叹号用于匹配除去特定集合中的任一字符。 |
debug[a-z].log |
debuga.log debugb.log 但不会匹配 debug1.log |
范围可以是数字,也可以是字母。 |
logs |
logs logs/debug.log logs/latest/foo.bar build/logs build/logs/debug.log |
如果你不后接斜杠,规则将会同时匹配相符的文件和目录。在左边的栗子中,名为 logs 的目录和文件都被忽略了。 |
| logs/ | logs/debug.log logs/latest/foo.bar build/logs/foo.bar build/logs/latest/debug.log |
后接斜杠表示该规则对应的是一个目录。仓库中符合该规则的任何目录中的所有内容(包括文件和子目录)都会被忽略。 |
logs/ !logs/important.log |
logs/debug.log logs/important.log |
注意,为什么左边栗子中被加上否定的 logs/important.log 没有被忽略?由于 Git 的性能优化,你 不能 否定一个根据目录匹配规则被忽略的文件。 |
logs/**/debug.log |
logs/debug.log logs/monday/debug.log logs/monday/pm/debug.log |
两个星号匹配零个或多个目录。 |
logs/*day/debug.log |
logs/monday/debug.log logs/tuesday/debug.log 但不会匹配* logs/latest/debug.log |
通配符也可被用于目录名中。 |
logs/debug.log |
logs/debug.log 但不会匹配* debug.log build/logs/debug.log |
一些规则指定特定目录下的文件,这些路径相对于仓库的根目录。你可以在前接一个斜杠,但这不是必须的。 |
** 这些解释假设你的 .gitignore 文件按照惯例位于仓库根目录。如果仓库中存在多个 .gitignore 文件,你只需要将“包含 .gitignore 文件的目录”想成是“仓库的根目录”。同时,为了便于团队合作,你应该考虑将它们合并*
除了这些符号之外,你可以使用 # 在 .gitignore 文件中添加注释:
# ignore all logs
*.log
你可以在 .gitignore 规则字符中使用 \ 转义,如果文件名或目录名中包含特殊字符:
# ignore the file literally named foo[01].txt
foo\[01\].txt
仓库内的共享 .gitignore 文件
Git 忽略规则通常被定义在仓库根目录的 .gitignore 文件中。但是,你也可以在仓库内不同文件夹下定义多个 .gitignore 文件。 .gitignore 文件中的每个规则都会在所在文件夹进行匹配。不过,我们一般只在根目录定义一个 .gitignore 文件,这也是最简单的做法。当 .gitignore 文件被检入时,它和仓库内其它所有文件一样也有版本,在你推送后将与他人共享。在 .gitignore 中,你应该只添加对其它用户也有用的规则。
个人的 Git 忽略规则
你可以在 .git/info/exclude 这个文件中为某个仓库定义个人的忽略规则。它们没有版本,也不会跟随仓库发布,因此它们适合存放只对你有用的规则。例如,如果你有一个自定义的登陆配置,火烧会在仓库的工作目录下生成文件的特殊开发工具,你可以将它们添加到 .git/info/exclude 以避免被意外提交到仓库中。
全局的 Git 忽略规则
此外,通过设置 Git 的 core.excludesFile 属性,你可以在本地系统中为所有仓库设置全局的 Git 忽略规则。你需要自己创建这个文件。如果你不确定在哪里放置这个全局的 .gitignore 文件,home 目录会是一个好的选择,也便于以后的查找。创建这个文件之后,你需要使用 git config 配置它的位置:
$ touch ~/.gitignore
$ git config --global core.excludesFile ~/.gitignore
你应该特别注意哪些规则是应该全局忽略的,因为不同的项目会用到不同类型的文件。某些操作系统文件(如 .DS_Store 和 thumbs.db)和开发者工具生成的临时文件往往可以被全局忽略。
忽略一个被提交过的文件
如果你想要忽略一个已经提交过的文件,你需要将这个文件从仓库中删除,然后在 .gitignore 中添加一条规则。使用 git rm 的 --cached 选项表示这个而文件将从仓库中被删除,但将作为一个被忽略的文件存在于工作目录下。
$ echo debug.log >> .gitignore
$ git rm --cached debug.log
rm 'debug.log'
$ git commit -m "Start ignoring debug.log"
如果你希望将某个文件同时从仓库和本地文件系统中删除,你可以省略 --cached 选项。
提交被忽略的文件
使用 git add 的 -f(或者--force)选项,你可以强制提交一个被忽略的文件:
$ cat .gitignore
*.log
$ git add -f debug.log
$ git commit -m "Force adding debug.log"
使用这个命令的一个场景是,你定义了一个通用的规则(如 *.log),但是想要提交某个特定的文件。不过,一个更好的解决方案是为这个通用的规则定义一个例外:
$ echo !debug.log >> .gitignore
$ cat .gitignore
*.log
!debug.log
$ git add debug.log
$ git commit -m "Adding debug.log"
上面的这个方法更加清晰易懂,尤其是对于其它团队成员。
储存被忽略的文件
git stash 是一个强大的 Git 功能。它将本地的更改临时储存起来然后撤销,允许你随后再重新应用这些更改。正如你所想的一样,git stash 默认跳过被忽略的文件,它只储存被 Git 追踪的文件中的更改。然后,你可以使用 git stash 的 --all 选项来储存被忽略和为追踪的文件。
调试 .gitignore 文件
如果你的 .gitignore 规则十分复杂,或者规则分散于多个 .gitignore 文件,要理解某个文件为什么被忽略了不是一件容易的事情。你可以使用 git check-ignore 命令的 -v(或者 --verbose)选项来确定是哪条规则让某个文件被忽略了:
$ git check-ignore -v debug.log
.gitignore:3:*.log debug.log
输出的格式如下:
<file containing the pattern> : <line number of the pattern> : <pattern> <file name>
你可以向 git check-ignore 传入多个文件名。这些文件名不一定要对应于仓库中已存在的文件。
这篇文章是「git-recipes」的一部分,点击 目录 查看所有章节。
如果你觉得文章对你有帮助,欢迎点击右上角的 Star 🌟 或 Fork 🍴。
如果你发现了错误,或是想要加入协作,请参阅 Wiki 协作说明。