繁体   English   中英

如何排除除了所有顶级点文件和子目录之外的所有内容?

[英]How can I exclude everything but all top-level dot files and a subdirectory?

在使用Git跟踪我的基本配置文件时,我在编写.gitignore文件时遇到问题。

我的目标是在我的存储库中包含两件事:

  1. 我的用户目录中的所有dotfiles ~/ ,这是我的gitroot。
  2. 隐藏文件夹~/.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

TL; DR

你正在遇到一个破坏你的用例的优化:一旦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/包含.netrwhistafter/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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM