- 10.8 文件忽略
- On branch master
- Changes to be committed:
- (use "git reset HEAD<file>…"to unstage)
- renamed:.gitignore->../.gitignore
- On branch master
- On branch master
- Changed but not updated:
- (use "git add<file>…" to update what will be committed)
- (use "git checkout—<file>…" to discard changes in working directory)
- modified:hello.h
- 这是注释行—被忽略
10.8 文件忽略
Git提供了文件忽略功能。当对工作区某个目录或某些文件设置了忽略后,再执行git status查看状态时,被忽略的文件即使存在也不会显示为未跟踪状态,甚至根本感觉不到这些文件的存在。现在就针对Hello world程序目录试验一下。
$cd/path/to/my/workspace/demo/src
$git status-s
?? hello
?? main.o
?? version.h
可以看到src目录下编译的目标文件等显示为未跟踪,每一行开头的两个问号好像在向我们请求:“快把我们添加到版本库里吧”。
执行下面的命令可以在这个目录下创建一个名为.gitignore的文件(注意文件的前面有个点),把这些要忽略的文件写在其中,文件名可以使用通配符。注意:第2行到第5行开头的右尖括号是cat命令的提示符,不是用户的输入。
$cat>.gitignore<<EOF
>hello
>*.o
>*.h
>EOF
看看写好的.gitignore文件。每个要忽略的文件显示在一行。
$cat.gitignore
hello
*.o
*.h
再来看看当前工作区的状态。
$git status-s
?? .gitignore
把.gitignore文件添加到版本库中吧。(如果不希望添加到库里,也不希望.gitignore文件带来干扰,可以在忽略文件中忽略自己。)
$git add.gitignore
$git commit-m "ignore object files."
[master b3af728]ignore object files.
1 files changed,3 insertions(+),0 deletions(-)
create mode 100644 src/.gitignore
1.文件.gitignore可以放在任何目录中
文件.gitignore的作用范围是其所处的目录及其子目录,因此如果把刚刚创建的.gitignore移动到上一层目录(仍位于工作区内)也应该有效,移动操作如下:
$git mv.gitignore..
$git status
On branch master
Changes to be committed:
(use "git reset HEAD<file>…"to unstage)
#
renamed:.gitignore->../.gitignore
#
果然移动.gitignore文件到上层目录,Hello world程序目录下的目标文件依然被忽略着。执行提交:
$git commit-m "move.gitignore outside also works."
[master 3488f2c]move.gitignore outside also works.
1 files changed,0 insertions(+),0 deletions(-)
rename src/.gitignore=>.gitignore(100%)
2.忽略文件有错误,后果很严重
实际上,上面写的忽略文件不是非常好,为了忽略version.h,结果使用了通配符*.h会把源码目录下的有用的头文件也给忽略掉,导致应该添加到版本库的文件忘记添加。
在当前目录下创建一个新的头文件hello.h。
$echo "/test/">hello.h
在工作区状态显示中看不到hello.h文件。
$git status
On branch master
nothing to commit(working directory clean)
只有使用了—ignored参数,才会在状态显示中看到被忽略的文件。
$git status—ignored-s
!! hello
!! hello.h
!! main.o
!! version.h
要添加hello.h文件,使用git add-A和git add.都失效。无法用这两个命令将hello.h添加到暂存区中。
$git add-A
$git add.
$git status-s
只有在添加操作的命令行中明确地写入文件名,并且提供-f参数才能真正添加。
$git add-f hello.h
$git commit-m "add hello.h"
[master 48456ab]add hello.h
1 files changed,1 insertions(+),0 deletions(-)
create mode 100644 src/hello.h
3.忽略只对未跟踪文件有效,对于已加入版本库的文件无效
文件hello.h添加到版本库后,就不再受到.gitignore设置的文件忽略所影响了,对hello.h的修改都会立刻被跟踪到。这是因为Git的文件忽略只是对未入库的文件起作用。
$echo "/end/">>hello.h
$git status
On branch master
Changed but not updated:
(use "git add<file>…" to update what will be committed)
(use "git checkout—<file>…" to discard changes in working directory)
#
modified:hello.h
#
no changes added to commit(use "git add" and/or "git commit-a")
偷懒式提交。(使用了-a参数提交,不用预先执行git add命令。)
$git commit-a-m" 偷懒了,直接用-a参数直接提交。"
[master 613486c]偷懒了,直接用-a参数直接提交。
1 files changed,1 insertions(+),0 deletions(-)
4.本地独享式忽略文件
文件.gitignore设置的文件忽略是共享式的。之所以称其为“共享式”,是因为.gitignore被添加到版本库后成为了版本库的一部分,当版本库共享给他人(克隆),或者把版本库推送(PUSH)到集中式的服务器(或他人的版本库)时,这个忽略文件就会出现在他人的工作区中,文件忽略在他人的工作区中同样生效。
与“共享式”忽略对应的是“独享式”忽略。独享式忽略就是不会因为版本库共享,或者版本库之间的推送传递给他人的文件忽略。独享式忽略有两种方式:
一种是针对具体版本库的“独享式”忽略。即在版本库.git目录下的一个文件.git/info/exclude来设置文件忽略。
另外一种是全局的“独享式”忽略。即通过Git的配置变量core.excludesfile指定的一个忽略文件,其设置的忽略对所有本地版本库均有效。
至于哪些情况需要通过向版本库中提交.gitignore文件设置共享式的文件忽略,哪些情况通过.git/info/exclude设置只对本地有效的独享式文件忽略,这取决于要设置的文件忽略是否具有普遍意义。如果文件忽略对于所有使用此版本库工作的人都有益,就通过在版本库相应的目录下创建一个.gitignore文件建立忽略;否则,如果是需要忽略工作区中创建的一个试验目录或试验性的文件,则使用本地忽略。
例如,我的本地就设置着一个全局的独享的文件忽略列表(这个文件名可以随意设置):
$git config—global core.excludesfile/home/jiangxin/.gitignore
$git config core.excludesfile
/home/jiangxin/.gitignore
$cat/home/jiangxin/.gitignore
*~#vim临时文件
*.pyc#python的编译文件
.*.mmx#不是正则表达式哦,因为FreeMind-MMX的辅助文件以点开头
5.Git忽略语法
关于Git的忽略文件的语法规则再多说几句:
忽略文件中的空行或以井号(#)开始的行会被忽略。
可以使用通配符,参见Linux手册:glob(7)。例如:星号(*)代表任意多字符,问号(?)代表一个字符,方括号([abc])代表可选字符范围等。
如果名称的最前面是一个路径分隔符(/),表明要忽略的文件在此目录下,而非子目录的文件。
如果名称的最后面是一个路径分隔符(/),表明要忽略的是整个目录,同名文件不忽略,否则同名的文件和目录都忽略。
通过在名称的最前面添加一个感叹号(!),代表不忽略。
下面的文件忽略示例,包含了上述要点:
这是注释行—被忽略
*.a # 忽略所有以.a为扩展名的文件。
!lib.a # 但是lib.a文件或目录不要忽略,即使前面设置了对*.a的忽略。
/TODO # 只忽略此目录下的TODO文件,子目录的TODO文件不忽略。
build/ # 忽略所有build/目录下的文件。
doc/*.txt # 忽略文件如doc/notes.txt,但是文件如doc/server/arch.txt不被忽略。