Files
git-recipes/sources/2.3.5-git_ignore.md
2018-12-24 23:19:48 +09:00

161 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# .gitignore
![Saving changes](https://wac-cdn.atlassian.com/dam/jcr:75f75cb6-a6ab-4f0b-ab29-e366914f513c/hero.svg?cdnVersion=kg)
***[git add](2.3.1-git_add.md) / [git commit](2.3.2-git_commit.md) / [git diff](2.3.3-git_diff.md) / [git stash](2.3.4-git_stash.md) / [.gitignore](2.3.5-git_ignore.md)***
> ✍️ [童仲毅](https://github.com/geeeeeeeeek) | ⏳ 2018 年 12 月 24 日
>
> ©️ 本文演绎自 Atlassian 编写的 [_Saving Changes_](https://www.atlassian.com/git/tutorials/saving-changes)。页面上所有内容采用知识共享-署名([CC BY 2.5 AU](http://creativecommons.org/licenses/by/2.5/au/deed.zh))许可协议。
Git 将工作副本中每个文件都视作以下三者之一:
1. 被追踪的文件——之前被缓存或提交过的文件;
2. 未被追踪的文件——尚未被缓存或提交过的文件;
3. 被忽略的文件——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 规则](http://linux.die.net/man/7/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` 文件中添加注释:
```shell
# ignore all logs
*.log
```
你可以在 `.gitignore` 规则字符中使用 \ 转义,如果文件名或目录名中包含特殊字符:
```shell
# 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` 配置它的位置:
```shell
$ touch ~/.gitignore
$ git config --global core.excludesFile ~/.gitignore
```
你应该特别注意哪些规则是应该全局忽略的,因为不同的项目会用到不同类型的文件。某些操作系统文件(如 `.DS_Store``thumbs.db`)和开发者工具生成的临时文件往往可以被全局忽略。
## 忽略一个被提交过的文件
如果你想要忽略一个已经提交过的文件,你需要将这个文件从仓库中删除,然后在 `.gitignore` 中添加一条规则。使用 `git rm``--cached` 选项表示这个而文件将从仓库中被删除,但将作为一个被忽略的文件存在于工作目录下。
```shell
$ echo debug.log >> .gitignore
$ git rm --cached debug.log
rm 'debug.log'
$ git commit -m "Start ignoring debug.log"
```
如果你希望将某个文件同时从仓库和本地文件系统中删除,你可以省略 `--cached` 选项。
## 提交被忽略的文件
使用 `git add``-f`(或者`--force`)选项,你可以强制提交一个被忽略的文件:
```shell
$ cat .gitignore
*.log
$ git add -f debug.log
$ git commit -m "Force adding debug.log"
```
使用这个命令的一个场景是,你定义了一个通用的规则(如 `*.log`),但是想要提交某个特定的文件。不过,一个更好的解决方案是为这个通用的规则定义一个例外:
```shell
$ 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`)选项来确定是哪条规则让某个文件被忽略了:
```shell
$ git check-ignore -v debug.log
.gitignore:3:*.log debug.log
```
输出的格式如下:
```shell
<file containing the pattern> : <line number of the pattern> : <pattern> <file name>
```
你可以向 `git check-ignore` 传入多个文件名。这些文件名不一定要对应于仓库中已存在的文件。
> 这篇文章是[**「git-recipes」**](https://github.com/geeeeeeeeek/git-recipes/)的一部分,点击 [**目录**](https://github.com/geeeeeeeeek/git-recipes/wiki/) 查看所有章节。
>
> 如果你觉得文章对你有帮助,欢迎点击右上角的 **Star** :star2: 或 **Fork** :fork_and_knife:。
>
> 如果你发现了错误,或是想要加入协作,请参阅 [Wiki 协作说明](https://github.com/geeeeeeeeek/git-recipes/issues/1)。