[英]How can I exclude everything but all top-level dot files and a subdirectory?
In keeping track of my essential configuration files with Git, I'm having trouble writing my .gitignore file. 在使用Git跟踪我的基本配置文件时,我在编写.gitignore文件时遇到问题。
My goal is to include two things in my repository: 我的目标是在我的存储库中包含两件事:
~/
, which is my gitroot. 我的用户目录中的所有dotfiles ~/
,这是我的gitroot。 ~/.vim/bundle
隐藏文件夹~/.vim/bundle
So far, I have tried the following approach, to no avail. 到目前为止,我尝试了以下方法,但无济于事。
.gitignore: 的.gitignore:
# Ignore everything
*
# Include top-level dot files.
!/.*
# Include vim plugins
!/.vim/bundle/*
This only stages the dotfiles in my gitroot. 这只会在我的gitroot中处理dotfiles。
Note. 注意。
My gitroot is my user directory ~/
. 我的gitroot是我的用户目录~/
。
Update 更新
In the following form, the ~/.vim
folder is staged: 在以下表格中, ~/.vim
文件夹已暂存:
# Ignore everything
*
# Include top-level dot files.
!/.*
# Include vim plugins
!/.vim
So, I'm guessing that I should express the pathname /.vim/bundle
differently, somehow. 所以,我猜我应该以某种方式表达路径名/.vim/bundle
。
You're running into an optimization that breaks your use case: once Git decides not to look inside a directory, it never finds the files within that directory that it would add. 你正在遇到一个破坏你的用例的优化:一旦Git决定不查看目录,它就永远不会在该目录中找到它将添加的文件。 To fix it you need at least one more rule: 要修复它,您至少还需要一个规则:
!/.vim/bundle/
You can use a different rule to defeat all optimization: 您可以使用其他规则来阻止所有优化:
!*/
which should also make the problem go away (at the expense of much deeper searches which result in a lot of slowness). 这也应该使问题消失(以更深入的搜索为代价,导致很多缓慢)。
You have a good start, but you have run into a problematic optimization (that the Git folks are, I think, trying to fix). 你有一个良好的开端,但你遇到了一个有问题的优化(我想,Git人员试图修复)。 We must also make assumptions about what is currently in your index (aka staging-area) as the index contents affect how Git scans through directories. 我们还必须假设索引中当前的内容(也就是暂存区域),因为索引内容会影响Git扫描目录的方式。 Let's assume that your index is truly empty, as it would be right after git init
-ing a new repository. 让我们假设你的索引真的是空的,因为它会在git init
a new repository之后。 That way, since there are no existing index entries, they cannot affect Git's normal directory-scanning process. 这样,由于没有现有的索引条目,它们不会影响Git的正常目录扫描过程。
Let's suppose your work-tree here has files named README
and .profile
, and directories d/
and .vim/
. 假设这里的工作树有名为README
和.profile
文件,以及目录d/
和.vim/
。 Your .gitignore
has three rules. 你的.gitignore
有三条规则。 The first one is a positive rule ("do ignore") and the second and third are negated rules ("don't ignore"). 第一个是正规则(“忽略”),第二个和第三个是否定规则(“不要忽略”)。 The rules themselves, minus the !
规则本身,减去!
, are: , 是:
*
/.*
/.vim/bundle/*
Now when Git is working on README
it first checks *
, which matches, then /.*
, which does not match, then /.vim/bundle/*
which also does not match. 现在当Git正在使用README
它首先检查*
,匹配,然后是/.*
,它们不匹配,然后是/.vim/bundle/*
,它们也不匹配。 The last matching rule takes effect: that's *
which says "do ignore" so README
will be ignored. 最后一个匹配规则生效:那个*
表示“忽略”,因此README
将被忽略。 The file .profile
, on the other hand, the first two rules, so the second one applies, and it says !
另一方面,文件.profile
是前两个规则,所以第二个规则适用,它说!
so .profile
is untracked but not ignored: git status
will whine about it, and git add .
所以.profile
是未跟踪但未被忽略的: git status
会对此抱怨,并且git add .
will add it to the index. 将它添加到索引。
Now let's consider how d/
and .vim/
are handled. 现在让我们考虑如何处理d/
和.vim/
。 These are directories, not files: Git is not going to save them, but it may or may not save files that are within them. 这些目录,而不是文件:Git是救不了他们,但它可能会或可能不会是保存在其中的文件。 To do so, it will have to read and check all the file names within them. 为此,它必须阅读并检查其中的所有文件名。 This is pretty expensive, so Git will first try to skip the directory entirely. 这是非常昂贵的,所以Git将首先尝试完全跳过该目录。 This is the problematic optimization I mentioned. 这是我提到的有问题的优化。
Anyway, d/
matches the first rule but not the other two. 无论如何, d/
匹配第一条规则但不匹配其他两条规则。 This means Git gets to skip reading d/
entirely . 这意味着Git的获取跳过读d/
完全 。 git status
will not whine about it and git add
will not scan it. git status
不会抱怨它, git add
也不会扫描它。
We're all good so far. 到目前为止,我们都很好。 .vim/
matches the second rule (but not the third) so Git will look inside .vim
. .vim/
匹配第二条规则(但不是第三条规则),所以Git会查看.vim
。
Let's say that .vim/
contains .netrwhist
, after/
, bundle/
, and maybe some other directories. 让我们说.vim/
包含.netrwhist
, after/
, bundle/
,也许还有其他一些目录。 .netrwhist
matches *
, does not match /.*
, and does not match /.vim/bundle/*
, so the *
match applies and it gets ignored. .netrwhist
匹配*
,与/.*
不匹配,与/.vim/bundle/*
不匹配,因此*
匹配适用并被忽略。 The after/
directory matches *
, does not match /.*
, and does not match /.vim/bundle/*
, so it goes unread. after/
目录匹配*
,与/.*
不匹配,与/.vim/bundle/*
不匹配,因此未读。
Now we hit the problem: .vim/bundle/
is a directory. 现在我们遇到了问题: .vim/bundle/
是一个目录。 Git checks this path name against your .gitignore
directives. Git根据.gitignore
指令检查此路径名。 bundle/
matches *
. bundle/
匹配*
。 .vim/bundle
does not match /.*
as that means files in the top level ; .vim/bundle
与/.*
不匹配,因为这意味着顶级文件 ; .vim/bundle/
is a directory and is not in the top level. .vim/bundle/
是一个目录,不在顶层。 The path also does not match the third directive /.vim/bundle/*
, which requires that this be a file or directory within .vim/bundle/
. 路径也不符第三指令/.vim/bundle/*
,这就要求这是中的文件或目录.vim/bundle/
。 So the only matching directive is the first one, and .vim/bundle
goes unread just like d/
did. 所以唯一匹配的指令是第一个,而.vim/bundle
就像d/
did一样未读 。
This means that Git never finds any of the files or directories within .vim/bundle/
. 这意味着Git永远不会在 .vim/bundle/
找到任何文件或目录。 It never checks the files (if any) against anything and it never scans the subdirectories for more files. 它永远不会检查任何文件(如果有的话),它从不扫描子目录中的更多文件。 You need to force Git to look inside .vim/bundle/
. 你需要强制Git查看.vim/bundle/
。
If there is some file in the index whose path name is .vim/bundle/a/b
, Git is going to have to scan the directory .vim/bundle/a
. 如果索引中的某个文件的路径名是.vim/bundle/a/b
,则Git将必须扫描目录.vim/bundle/a
。 So any new files placed in there will show up! 所以放在那里的任何新文件都会出现! I'm not sure if Git ever skips .vim/bundle/
itself in this case (in theory it could but I don't think it does in practice). 我不确定Git是否会在这种情况下跳过.vim/bundle/
本身(理论上它可以,但我不认为它在实践中有效)。 Once you have a file path in the index, that file is tracked and its presence in any .gitignore
becomes irrelevant. 一旦索引中有文件路径,就会跟踪该文件,并且它在任何.gitignore
存在都变得无关紧要。
Note, however, that files that are in the index now are not necessarily in the index tomorrow , if you remove them or if you check out some other commit where those files are not present. 但是,请注意,索引中的文件现在不一定在明天的索引中,如果您删除它们,或者如果您检查其他提交文件不存在的那些文件。 The whole thing is a little bit tricky. 整件事情有点棘手。
The leading slash indicates an absolute path relative to gitroot; 前导斜杠表示相对于gitroot的绝对路径; remove it to select all dotfiles. 删除它以选择所有dotfiles。
# Ignore everything
*
# Include all dot files.
!.*
# Include vim plugins
!/.vim/bundle/*
Here is a handy and concise reference with examples. 这是一个方便,简洁的参考示例。
You will need to stage and then commit .gitignore
for the changes to take effect. 您需要.gitignore
然后提交.gitignore
才能使更改生效。 Happily you can repeatedly git commit --amend
with further changes to keep the history clean until you have what you want. 令人高兴的是,您可以反复git commit --amend
并进行进一步更改,以保持历史记录清洁,直到您拥有所需内容。
As a vaguely-related aside, I've often seen people attempt to match "a folder of name folder
anywhere in the project" with /folder
, where it ought to be **/folder
. 作为一个模糊相关的旁边,我经常看到有人试图将“项目中任意位置的文件folder
”与/folder
匹配,它应该是**/folder
。
I was inspired by this answer to write the following adequate .gitignore
file. 我从这个答案中受到启发,写下以下适当的.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.