Git 忽略目录和目录/* 的区别是什么?

我对忽略 git 中目录内容的正确方法感到困惑。

假设我有以下目录结构:

my_project
|--www
|--1.txt
|--2.txt
|--.gitignore

写这个和写这个有什么区别:

www

这个呢?

www/*

我问这个问题的原因是: 在 git 中,如果一个目录是空的,git 就不会在存储库中包含这样的空目录。所以我尝试的解决方案是增加一个额外的。目录下的 gitkeep 文件,这样它就不会是空的。当我尝试这个解决方案时,如果在。Gitignore 文件,我写如下:

www
!*.gitkeep

它不工作(我的意图是忽略 www 下的所有内容,但保留目录)。但如果我试试以下方法:

www/*
!*.gitkeep

然后它工作! 所以我认为它必须有一些区别,在这两种方法之间。

5010 次浏览

I'm just parsing through the documentation, and as far as I can tell they only differ in more advanced patterns, e.g.

$ cat .gitignore
# exclude everything except directory foo/bar
/*
!/foo
/foo/*
!/foo/bar

I did test the above, and if you replace !/foo with !/foo/*, you do indeed get a different result.

Note

foo

Will exclude any file foo, but

foo/

will only exclude directories named foo.

There're differences among www, www/ and www/*.

Basically from the documentation and my own tests, www find a match with a file or a directory, www/ only matches a directory, while www/* matches directories and files inside www.

I'll only discuss on the differences between www/ and www/* here, since the differences between www and www/ are obvious.

For www/, git ignores the directory www itself, which means git won't even look inside. But for www/*, git checks all files/folders inside www, and ignores all of them with the pattern *. It seems to lead to the same results since git won't track an empty folder www if all its child files/folders are ignored. And indeed the results will be no difference for OP's case with www/ or www/* standalone. But it does make differences if it's combined with other rules.

For example, what if we want to only include www/1.txt but ignore all others inside www?

The following .gitignore won't work.

www/
!www/1.txt

While the following .gitignore works, why?

www/*
!www/1.txt

For the former, git just ignores the directory www, and won't even look inside to include www/1.txt again. The first rule excludes the parent directory www but not www/1.txt, and as a result www/1.txt cannot be "included again".

But for the latter, git first ignores all files/folers under www, and then includes one of them again which is www/1.txt.

For this example, the follwing lines in the documentation may help:

An optional prefix "!" which negates the pattern; any matching file excluded by a previous pattern will become included again. It is not possible to re-include a file if a parent directory of that file is excluded.

Apart from the perfectly good answers you have already obtained, you should note that you can have .gitignore anywhere in your project, including subfolders.

So if you want to ignore all files inside www, but whant the www folder to be versioned, instead of using an empty .gitkeep, .dummy or whatever name you choose, why not use a .gitignore there, telling to ignore all files?

/
|- .gitignore   (a)
\- www
|- .gitignore   (b)
|- 1.jpg
\- 2.jpg

In the root .gitignore (a), you don't say anything about the www folder or its contents.

In the www/.gitignore (b) you put the following:

# ignore all files in this folder except this .gitignore
*
!.gitignore

This way everything looks more organized (to me at least).

To ignore everything in a directory except dotfiles you can use the following glob-pattern in your .gitignore:

www/[^.]*

So no need for an extra .gitignore, just simply add a .keep file to your www directory.