代码之家  ›  专栏  ›  技术社区  ›  Mussé Redi

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

  •  3
  • Mussé Redi  · 技术社区  · 6 年前

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

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

    1. 我的用户目录中的所有点文件 ~/ ,这是我的gitroot。
    2. 隐藏文件夹 ~/.vim/bundle

    到目前为止,我尝试了以下方法,但没有成功。

    .gitignore:

    # Ignore everything
    *
    
    # Include top-level dot files.
    !/.*
    
    # Include vim plugins
    !/.vim/bundle/*
    

    这只会在我的gitroot中暂存点文件。

    笔记

    我的gitroot是我的用户目录 ~/ .

    使现代化

    在以下形式中 ~/.vim 文件夹 分阶段:

    # Ignore everything
    *
    
    # Include top-level dot files.
    !/.*
    
    # Include vim plugins
    !/.vim
    

    所以,我猜我应该表示路径名 /.vim/bundle 不知何故,情况有所不同。

    3 回复  |  直到 6 年前
        1
  •  3
  •   torek    6 年前

    TL;博士

    您遇到了一个破坏您的用例的优化:一旦Git决定不查看目录,它就永远找不到文件 在内部 它将添加的目录。要解决此问题,您至少还需要一条规则:

    !/.vim/bundle/
    

    您可以使用不同的规则来击败所有优化:

    !*/
    

    这也会让问题消失(以更深入的搜索为代价,这会导致速度变慢)。

    长的

    您有了一个良好的开端,但遇到了一个有问题的优化问题(我认为Git人员正在努力解决这个问题)。我们还必须对您的 指数 git init -正在初始化新存储库。这样,由于没有现有的索引项,它们不会影响Git的正常目录扫描过程。

    假设您的工作树中有名为 README .profile ,和目录 d/ .vim/ . 你的 .gitignore ! ,是:

    *
    /.*
    /.vim/bundle/*
    

    现在Git正在进行 自述文件 * ,则匹配 /.* ,则不匹配 /.vim/bundle/* 这也不匹配。最后一条匹配规则生效:即 * 上面写着“不要理会”所以 自述文件 将被忽略。文件 .轮廓 另一方面,前两条规则,所以第二条规则适用,它说 ! 所以 .轮廓 未跟踪但未忽略: git status 会抱怨的,而且 git add . 将其添加到索引中。

    现在让我们考虑一下 d/ .vim公司/ 已处理。这些是目录,而不是文件:Git不会保存它们,但它可能会也可能不会保存 在内部 他们为此,它必须读取并检查其中的所有文件名。这相当昂贵,所以Git将首先尝试 跳过 整个目录。这就是我提到的有问题的优化。

    无论如何 d/ 匹配第一条规则,但不匹配其他两条规则。这意味着Git可以 跳过阅读 d/ 完全 . git状态 不会抱怨 git add 不会扫描它。

    到目前为止,我们都很好。 .vim公司/ 匹配第二条规则(但不是第三条),因此Git将查看内部 .vim .

    这么说吧 .vim公司/ 包含 .netrwhist , after/ , bundle/ ,可能还有其他目录。 .网络历史 比赛 * ,不匹配 /.* ,并且不匹配 /.vim/线束/* ,因此 * match应用并被忽略。这个 之后/ 目录匹配项 * ,不匹配 /.* ,并且不匹配 /.vim/线束/* ,因此未读。

    现在我们遇到了问题: .vim/bundle/ 是一个目录。Git根据您的 .gitignore 指令。 捆绑/ 比赛 * . .vim/bundle 不匹配 /.* 也就是说 顶层文件 ; .vim/线束/ 是目录,不在顶层。路径也与第三条指令不匹配 /.vim/线束/* ,它要求这是一个文件或目录 在内部 .vim/线束/ . 所以 唯一匹配的指令是第一个指令,并且 .vim/线束 未读 就像 d/

    这意味着Git从未找到任何文件或目录 在内部 .vim/线束/ . 它从不检查文件(如果有),也从不扫描子目录以查找更多文件。你需要强迫Git看看里面 .vim/线束/ .

    索引中的条目变化很大

    如果索引中有路径名为的文件 .vim/bundle/a/b ,Git必须扫描目录 .vim/bundle/a . 所以有 放在那里的文件会显示出来!我不确定Git是否跳过 .vim/线束/ 在这种情况下(理论上可以,但我认为在实践中不行)。索引中有文件路径后,该文件将 跟踪 以及在任何 .gitignore 变得无关紧要。

    但是,请注意,索引中的文件 现在 不一定在索引中 明天 ,如果您删除了这些文件,或者如果您签出了其他一些没有这些文件的提交。整个事情有点棘手。

        2
  •  3
  •   msanford    6 年前

    前斜杠表示相对于gitroot的绝对路径;删除它以选择所有点文件。

    # Ignore everything
    *
    
    # Include all dot files.
    !.*
    
    # Include vim plugins
    !/.vim/bundle/*
    

    Here is 一个方便和简洁的参考例子。

    你需要先准备,然后提交 .gitignore 使更改生效。很高兴你可以重复 git commit --amend 进行进一步的更改,以保持历史记录的完整性,直到获得所需的内容。

    顺便说一句,我经常看到人们试图匹配“一个文件夹的名字” folder 项目中的任何位置 /folder ,应该在哪里 **/folder .

        3
  •  0
  •   Mussé Redi    6 年前

    我的灵感来自 this answer 编写以下适当的 .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