更新:
有一个更简单的解决方案:
*
!*/
!/app/etc/modules/Some_Ext.xml
!/app/code/local/Some/Ext/
!/app/designer/...
... - etc.
第二行将再次包含所有目录,然后以下模式可以生效。
好吧,已经探索了源代码,我发现“gitignore”机制在某种程度上确实很棘手。
几点总结如下:
小心忽略目录。Git 以递归方式搜索未跟踪的文件,忽略目录将导致 git 跳过该目录并自动忽略该目录下的所有文件/子目录,即使您有“非”模式。所以
/app
!/app/code/index.php
不会保存index.php
,它将与 一起被忽略/app
。
尽力而为,*.xml/txt/conf/etc...
改用。永远不要使用standalone 是个好主意,*
因为它会忽略任何目录,这可能不是您想要的。
没有优先级,只有顺序。对于目录或文件,git.gitignore
逐行匹配路径并使用最后匹配的模式。如果最后匹配的模式有一个前导!
,git 将包含文件/目录,否则将忽略它。
所以
*.xml
!/app/etcmodules/Some_Ext.xml
将保留Some_Ext.xml
但
!/app/etcmodules/Some_Ext.xml
*.xml
会将其过滤掉。
将 git 更新到 1.8.2 版本可能会有所帮助。在 1.8.2 中,他们添加了一个git check-ignore
用于调试.gitignore
配置的命令。
我认为工作流程git add -A
可以解释更多。
假设有一个这样的存储库。
.
├── a.conf
├── b
│ └── b.conf
└── c
└── c1
└── c2
└── c.conf
其中.gitignore
有
*.conf
b/
!b/b.conf
!c/c1/c2/c.conf
当我运行时git add -A
,git会
- 扫描工作目录,发现有一个普通文件
a.conf
和两个目录b
和c
.
- 注意文件
a.conf
匹配*.conf
,.gitignore
然后忽略它。
b
是一个目录,但被模式排除在外b/
,.gitignore
停止递归到b
.
- 因为
b
被排除,b/b.conf
从未被扫描过。(虽然他不排除在第三行.gitignore
)
c
是一个目录,看起来还不错,包含它并继续递归到它。
c/c1/c2/c.conf
匹配两种模式,但最后一种决定命运。因为最后匹配的模式!c/c1/c2/c.conf
有一个前导!
,所以c/c1/c2/c.conf
会继续存在。
这是git add -A
在我的机器上的结果(带有 1.8.2 版 git 的 Mac)
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: .gitignore
# new file: c/c1/c2/c.conf