5.忽略Git
中的文件¶
你已经花了不少时间学习如何让Git
追踪仓库中的文件,以及如何处理Git
对你的活动几乎无时无刻的监视。所以你可能会觉得奇怪,为什么要让Git
主动忽略你仓库里的东西。
为什么你不希望Git
追踪你项目中的一切呢?好吧,在很多情况下,你可能不希望Git
追踪所有东西。
一个很好的例子是任何包含API
密钥、令牌、密码或其他秘密的文件,你肯定需要进行测试,但你不希望它们放在仓库里--尤其是公共仓库--让所有人看到。
根据你的开发平台,你可能有很多构建工件或生成的内容在你的项目目录里,比如链接器文件、元数据、生成的可执行文件和其他类似的东西。这些文件在你每次构建项目时都会重新生成,所以你肯定不希望Git
跟踪这些文件。还有那些顽固的东西,有些操作系统不经询问就把它们添加到你的目录里,比如macOS
上的.DS_Store
文件。
引入.gitignore
¶
Git
对此的回答是.gitignore
文件,它是一组保存在文件中的规则,告诉Git
不要追踪文件或文件集。这似乎是一个非常简单的解决方案,而且确实如此。但.gitignore
的真正威力在于它能够对各种文件进行模式匹配,这样你就不必对每一个你想让Git
忽略的文件进行说明,你甚至可以指示Git
忽略多个项目中的相同类型的文件。再进一步,你可以有一个适用于所有仓库的全局的.gitignore
,然后把特定项目的.gitignore
文件放在需要特别严格控制的项目的目录或子目录中。
在本章中,你将学习如何配置你自己的.gitignore
,如何使用一些来自GitHub
等地方的预制.gitignore
文件,以及如何设置一个适用于所有项目的全球.gitignore
。
开始工作¶
想象一下,在你的武器库中,有一个工具可以将你的markdown
"构建"成HTML
,以准备将你令人惊叹的书、教程和其他想法部署到一个私人网站,供你的团队评论。
在这种情况下,HTML
文件是生成的内容,你不想在版本库中跟踪。你想把它们作为构建过程的一部分在本地渲染,这样你就可以预览它们,但你绝不会直接编辑HTML
。它总是用工具渲染的。
在你项目的根目录下创建一个新的目录来存放这些生成的文件,使用下面的命令:
mkdir sitehtml
现在,在那里创建一个空的HTML
文件(保持想象力,朋友),使用以下命令:
touch sitehtml/all-todos.html
运行git status
,看看Git
是否识别了新内容:
~/GitApprentice/ideas $ git status
On branch main
Your branch is ahead of 'origin/main' by 7 commits.
(use "git push" to publish your local commits)
Untracked files:
(use "git add <file>..." to include in what will be committed)
sitehtml/
nothing added to commit but untracked files present (use "git add" to track)
因此,Git
又一次看到了你在做什么。但这里是如何让Git
视而不见的。
在你项目的根目录下创建一个名为.gitignore
的文件:
touch .gitignore
并使用文本编辑器在你新创建的.gitignore
中添加以下一行:
*.html
保存并退出。你所做的是告诉Git
,"对于这个项目,忽略所有符合这个模式的文件"。在这个例子中,你要求它忽略所有扩展名为.html
的文件。
现在,看看git status
告诉你什么:
~/GitApprentice/ideas $ git status
On branch main
Your branch is ahead of 'origin/main' by 7 commits.
(use "git push" to publish your local commits)
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
nothing added to commit but untracked files present (use "git add" to track)
Git
看到你添加了.gitignore
,但它不再认为那个HTML
文件是"未被追踪的",即使它被埋在一个子目录里。
现在,如果你对忽略子目录中的HTML文件没有意见,但你想让项目顶层目录中的所有HTML文件都被跟踪呢?理论上,你可以在每个子目录中重新创建相同的.gitignore
文件,并删除这个顶层的.gitignore
,但这将是非常繁琐的,而且不能很好地扩展。
相反,你可以在顶层的.gitignore
中使用一些巧妙的模式匹配,只忽略子目录。
编辑你的.gitignore
中的单行,如下所示:
*/*.html
保存并退出。这个新模式告诉Git
,"忽略所有不在顶层目录中的HTML
文件"。
为了证明这一点,在项目的顶层目录下创建一个新的HTML文件:
touch index.html
运行git status
,看看Git
是否真的识别了顶层目录中的HTML
文件,而仍然忽略了下面的文件:
~/GitApprentice/ideas $ git status
On branch main
Your branch is ahead of 'origin/main' by 7 commits.
(use "git push" to publish your local commits)
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
index.html
nothing added to commit but untracked files present (use "git add" to track)
Git
看到顶层的HTML
文件没有被追踪,但它仍然忽略了sitehtml
目录下的另一个HTML
文件,就像你计划的那样。
嵌套.gitignore
文件¶
你可以在你的项目中轻松地嵌套.gitignore
文件。想象一下,你有一个子目录,里面有从index.html
引用的HTML
文件。这些文件不是由你想象中的构建过程生成的,而是由手工维护的,你想确保Git
能够跟踪这些文件。
创建一个新目录,命名为htmlrefs
:
mkdir htmlrefs
现在,在该子目录下创建一个HTML
文件:
touch htmlrefs/utils.html
并在该目录下创建一个.gitignore
文件:
touch htmlrefs/.gitignore
打开htmlrefs/.gitignore
并添加以下一行:
!/*.html
保存并退出。惊叹号(!)
在这种情况下否定了模式,而斜线(/)
意味着"从这个目录开始执行这个规则"。所以这条规则说:"尽管有更高级别的规则,但不要忽略任何HTML
文件,从这个目录或更低的目录开始。"
执行git status
来看看这是否是真的:
~/GitApprentice/ideas $ git status
On branch main
Your branch is ahead of 'origin/main' by 7 commits.
(use "git push" to publish your local commits)
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
htmlrefs/
index.html
nothing added to commit but untracked files present (use "git add" to track)
现在Git把htmlrefs
目录下的内容看作是未被追踪的,就像你想的那样。
现在你对当前.gitignore
文件的安排感到满意了,你可以对这些改动进行阶段化和提交。
用下面的命令将所有的修改分阶段:
git add .
并把这些变化也提交上去:
git commit -m "Adding .gitignore files and HTML"
在每个项目的基础上设置.gitignore
文件,只能让你走到这一步。有些东西--比如前面提到的.DS_Store
文件,macOS
地将其添加到你的目录中--你想一直忽略它们。Git
有一个global .gitignore
的概念,你可以用来处理这样的情况。
查看全局.gitignore
¶
执行下面的命令,看看你是否已经有一个全局的.gitignore
:
git config --global core.excludesfile
如果该命令没有返回,那么你还没有设置好。不用担心;创建一个很容易。
在一个方便的地方创建一个文件--在这种情况下,就是你的主目录--并给它起一个明显的名字:
touch ~/.gitignore_global
现在你可以用git config
命令告诉Git
,它应该从现在开始把这个文件作为你的全局.gitignore
来看:
git config --global core.excludesfile ~/.gitignore_global
所以现在如果我问Git
我的全局.gitignore
在哪里,它会告诉我如下:
~/GitApprentice/ideas $ git config --global core.excludesfile
/Users/chrisbelanger/.gitignore_global
但现在你有了一个全局的.gitignore
......你应该把什么放在里面?
寻找.gitignore
文件样本¶
这是其中一种情况,你不必重新发明轮子。成千上万的开发者在你之前,他们已经找出了适合你特定情况的最佳配置。
一个更好的预制.gitignore
文件集合是由GitHub
托管的--我相信这并不奇怪。GitHub
有大多数操作系统、编程语言和代码编辑器的文件。
请到https://github.com/github/gitignore,看看它提供的软件包。适合你的操作系统的样本文件可以在资源库的Global
子文件夹中找到。
进入Global
子文件夹(或者直接导航到https://github.com/github/gitignore/tree/master/Global),找到适合你本地系统的。
有一个Windows.gitignore
,一个macOS.gitignore
,一个Linux.gitignore
,还有更多,都等着你把它们加入你自己的.gitignore
。这就是本章的挑战!
挑战¶
挑战:填充你的全局.gitignore
¶
这个挑战应该很简单,为你的全局.gitignore
提供一个好的起点。你的目标是为自己的操作系统找到正确的.gitignore
,从GitHub
仓库获取该文件,并将该文件的内容添加到你的全局.gitignore
。
- 导航到https://github.com/github/gitignore/tree/master/Global。
- 为你自己的操作系统找到正确的
.gitignore
。 - 将特定操作系统的
.gitignore
的内容添加到你自己的全局.gitignore
。
如果你被卡住了,或者想检查你的解决方案,你可以在本章的challenge
文件夹中找到这个挑战的答案。
关键点¶
.gitignore
可以让你配置Git
,让它忽略特定的文件或符合特定模式的文件。*.html
在你的.gitignore
中匹配你项目的任何目录或子目录中的所有以.html
为扩展名的文件。*/*.html
匹配所有以.html
为扩展名的文件,但只在项目的子目录下。!
否定一个匹配规则。- 你可以在项目的不同目录下有多个
.gitignore
文件来覆盖项目中更高层次的匹配。 - 你可以通过
git config --global core.excludesfile
命令找到你的全局.gitignore
的位置。 GitHub
在https://github.com/github/gitignore,提供了一些很好的.gitignore
起始文件。
接下来去哪?¶
随着你在越来越复杂的项目上工作,特别是跨越多种代码和编码语言,你会发现全局的.gitignore
的力量,加上特定项目(甚至特定文件夹)的.gitignore
文件,将成为你的Git
工作流程中不可缺少的一部分。
下一章将带你简短地了解一下git log
的各种工作原理。是的,你已经用过这个命令了,但这个命令有一些聪明的选项,可以帮助你以一种高效且高度可读的方式查看项目的历史。