[英]How can I exclude everything but all top-level dot files and a subdirectory?
在使用Git跟踪我的基本配置文件时,我在编写.gitignore文件时遇到问题。
我的目标是在我的存储库中包含两件事:
~/
,这是我的gitroot。 ~/.vim/bundle
到目前为止,我尝试了以下方法,但无济于事。
的.gitignore:
# Ignore everything
*
# Include top-level dot files.
!/.*
# Include vim plugins
!/.vim/bundle/*
这只会在我的gitroot中处理dotfiles。
注意。
我的gitroot是我的用户目录~/
。
更新
在以下表格中, ~/.vim
文件夹已暂存:
# Ignore everything
*
# Include top-level dot files.
!/.*
# Include vim plugins
!/.vim
所以,我猜我应该以某种方式表达路径名/.vim/bundle
。
你正在遇到一个破坏你的用例的优化:一旦Git决定不查看目录,它就永远不会在该目录中找到它将添加的文件。 要修复它,您至少还需要一个规则:
!/.vim/bundle/
您可以使用其他规则来阻止所有优化:
!*/
这也应该使问题消失(以更深入的搜索为代价,导致很多缓慢)。
你有一个良好的开端,但你遇到了一个有问题的优化(我想,Git人员试图修复)。 我们还必须假设索引中当前的内容(也就是暂存区域),因为索引内容会影响Git扫描目录的方式。 让我们假设你的索引真的是空的,因为它会在git init
a new repository之后。 这样,由于没有现有的索引条目,它们不会影响Git的正常目录扫描过程。
假设这里的工作树有名为README
和.profile
文件,以及目录d/
和.vim/
。 你的.gitignore
有三条规则。 第一个是正规则(“忽略”),第二个和第三个是否定规则(“不要忽略”)。 规则本身,减去!
, 是:
*
/.*
/.vim/bundle/*
现在当Git正在使用README
它首先检查*
,匹配,然后是/.*
,它们不匹配,然后是/.vim/bundle/*
,它们也不匹配。 最后一个匹配规则生效:那个*
表示“忽略”,因此README
将被忽略。 另一方面,文件.profile
是前两个规则,所以第二个规则适用,它说!
所以.profile
是未跟踪但未被忽略的: git status
会对此抱怨,并且git add .
将它添加到索引。
现在让我们考虑如何处理d/
和.vim/
。 这些目录,而不是文件:Git是救不了他们,但它可能会或可能不会是保存在其中的文件。 为此,它必须阅读并检查其中的所有文件名。 这是非常昂贵的,所以Git将首先尝试完全跳过该目录。 这是我提到的有问题的优化。
无论如何, d/
匹配第一条规则但不匹配其他两条规则。 这意味着Git的获取跳过读d/
完全 。 git status
不会抱怨它, git add
也不会扫描它。
到目前为止,我们都很好。 .vim/
匹配第二条规则(但不是第三条规则),所以Git会查看.vim
。
让我们说.vim/
包含.netrwhist
, after/
, bundle/
,也许还有其他一些目录。 .netrwhist
匹配*
,与/.*
不匹配,与/.vim/bundle/*
不匹配,因此*
匹配适用并被忽略。 after/
目录匹配*
,与/.*
不匹配,与/.vim/bundle/*
不匹配,因此未读。
现在我们遇到了问题: .vim/bundle/
是一个目录。 Git根据.gitignore
指令检查此路径名。 bundle/
匹配*
。 .vim/bundle
与/.*
不匹配,因为这意味着顶级文件 ; .vim/bundle/
是一个目录,不在顶层。 路径也不符第三指令/.vim/bundle/*
,这就要求这是中的文件或目录.vim/bundle/
。 所以唯一匹配的指令是第一个,而.vim/bundle
就像d/
did一样未读 。
这意味着Git永远不会在 .vim/bundle/
找到任何文件或目录。 它永远不会检查任何文件(如果有的话),它从不扫描子目录中的更多文件。 你需要强制Git查看.vim/bundle/
。
如果索引中的某个文件的路径名是.vim/bundle/a/b
,则Git将必须扫描目录.vim/bundle/a
。 所以放在那里的任何新文件都会出现! 我不确定Git是否会在这种情况下跳过.vim/bundle/
本身(理论上它可以,但我不认为它在实践中有效)。 一旦索引中有文件路径,就会跟踪该文件,并且它在任何.gitignore
存在都变得无关紧要。
但是,请注意,索引中的文件现在不一定在明天的索引中,如果您删除它们,或者如果您检查其他提交文件不存在的那些文件。 整件事情有点棘手。
前导斜杠表示相对于gitroot的绝对路径; 删除它以选择所有dotfiles。
# Ignore everything
*
# Include all dot files.
!.*
# Include vim plugins
!/.vim/bundle/*
这是一个方便,简洁的参考示例。
您需要.gitignore
然后提交.gitignore
才能使更改生效。 令人高兴的是,您可以反复git commit --amend
并进行进一步更改,以保持历史记录清洁,直到您拥有所需内容。
作为一个模糊相关的旁边,我经常看到有人试图将“项目中任意位置的文件folder
”与/folder
匹配,它应该是**/folder
。
我从这个答案中受到启发,写下以下适当的.gitignore
文件。 :)
# We use a whitelisting approach to track certain configuration files.
# Apparently, this needs to be done recursively because git can't see past a directory that is not
# included. Hence, if we want to include a subdirectory, we first need to include its upper
# directory, by the whitelisting procedure as shown below.
# Exclude all files and non-hidden directories.
/*
# Include all dotfiles.
!.*
# Exclude all hidden directories.
.*/
# Include the upper directory.
!/.vim
# Exclude all files and non-hidden directories.
/.vim/*
# Include the vim plugins.
!/.vim/bundle
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.