简体中文 ▾ 主题 ▾ 最新版本 ▾ gitignore 最后更新于 2.55.0

名称

gitignore - 指定 Git 故意忽略的未追踪文件

概要

$XDG_CONFIG_HOME/git/ignore, $GIT_COMMON_DIR/info/exclude, .gitignore

描述

gitignore 文件用于指定 Git 应该忽略的故意未追踪的文件。已经被 Git 追踪的文件不受影响;详见下文的“注意”部分。

gitignore 文件中的每一行指定一个模式。在决定是否忽略某个路径时,Git 通常会检查多个来源的 gitignore 模式,其优先级从高到低排列如下(在同一优先级内,最后匹配的模式决定结果):

  • 从支持它们的命令的命令行读取的模式。

  • 从与路径同目录或任何父目录(直至工作树的顶层)中的 .gitignore 文件读取的模式;高层目录文件中的模式会被下层目录(直至包含该文件的目录)中的模式覆盖。这些模式是相对于 .gitignore 文件位置进行匹配的。项目通常会将此类 .gitignore 文件包含在仓库中,其中包含项目构建过程中生成的文件的模式。

  • $GIT_COMMON_DIR/info/exclude 读取的模式。

  • 从配置变量 core.excludesFile 指定的文件中读取的模式。

将模式放置在哪个文件中取决于该模式的用途。

  • 应该被版本控制并分发到其他仓库(即所有开发人员都希望忽略的文件)的模式,应该放入 .gitignore 文件中。

  • 特定于某个仓库但不需要与其他相关仓库共享的模式(例如,驻留在仓库内但特定于某个用户工作流程的辅助文件),应该放入 $GIT_COMMON_DIR/info/exclude 文件中。

  • 用户希望 Git 在任何情况下都忽略的模式(例如,由用户选择的编辑器生成的备份或临时文件),通常放入用户 ~/.gitconfig 中由 core.excludesFile 指定的文件中。其默认值为 $XDG_CONFIG_HOME/git/ignore。如果未设置 $XDG_CONFIG_HOME 或为空,则改用 $HOME/.config/git/ignore。

基础 Git 底层工具(如 git ls-filesgit read-tree)会读取命令行选项指定的 gitignore 模式,或从命令行选项指定的文件中读取。更高级的 Git 工具(如 git statusgit add)则使用上述来源指定的模式。

模式格式

  • 空行不匹配任何文件,因此可以用作可读性分隔符。

  • 以 # 开头的行作为注释。对于以井号开头的模式,请在第一个井号前加反斜杠("\")。

  • 除非使用反斜杠("\")转义,否则尾随空格将被忽略。

  • 可选的前缀 "!" 用于否定模式;任何被先前模式排除的匹配文件都将再次被包含。如果一个文件的父目录已被排除,则无法重新包含该文件。出于性能考虑,Git 不会列出被排除的目录,因此无论在哪里定义,包含在其中的文件的任何模式都不会生效。对于以字面量 "!" 开头的模式,请在第一个 "!" 前加反斜杠("\"),例如 "\!important!.txt"。

  • 斜杠 "/" 用作目录分隔符。分隔符可以出现在 .gitignore 搜索模式的开头、中间或结尾。

  • 如果模式的开头或中间(或两者)有分隔符,则该模式是相对于特定的 .gitignore 文件所在的目录级别的。否则,该模式也可以匹配 .gitignore 级别之下的任何级别。

  • 从工作树之外的排除来源(如 $GIT_COMMON_DIR/info/exclude 和 core.excludesFile)读取的模式,将被视为在工作树的根目录下指定,即此类模式中的前导 "/" 将匹配锚定在仓库根目录。

  • 如果模式末尾有分隔符,则该模式仅匹配目录;否则,该模式既可以匹配文件,也可以匹配目录。

  • 例如,模式 doc/frotz/ 匹配 doc/frotz 目录,但不匹配 a/doc/frotz 目录;然而 frotz/ 匹配 frotza/frotz(如果它们是目录)(所有路径都是相对于 .gitignore 文件的)。

  • 星号 "*" 匹配除斜杠外的任何内容。字符 "?" 匹配除 "/" 外的任何单个字符。范围表示法(例如 [a-zA-Z])可用于匹配范围内的单个字符。有关详细描述,请参见 fnmatch(3) 和 FNM_PATHNAME 标志。

  • 反斜杠("\")可用于转义任何字符。例如,"\*" 匹配字面量的星号("\a" 匹配 "a",尽管在那里不需要转义)。与 fnmatch(3) 一样,模式末尾的反斜杠是无效模式,永远不会匹配。

与完整路径名匹配的模式中,两个连续的星号(**)可能具有特殊含义:

  • 以 "**" 开头后跟斜杠表示匹配所有目录。例如,"**/foo" 匹配任何位置的文件或目录 "foo",与模式 "foo" 相同。"**/foo/bar" 匹配直接位于目录 "foo" 下的任何位置的文件或目录 "bar"。

  • 尾随的 "/**" 匹配内部的所有内容。例如,"abc/**" 匹配目录 "abc" 内的所有文件(相对于 .gitignore 文件所在位置),深度不限。

  • 斜杠后跟两个连续的星号,然后是斜杠,匹配零个或多个目录。例如,“a/**/b”匹配“a/b”、“a/x/b”、“a/x/y/b”等等。

  • 其他连续的星号被视为普通星号,并将根据上述规则进行匹配。

配置

可选的配置变量 core.excludesFile 指向一个包含要排除的文件名模式的文件路径,类似于 $GIT_COMMON_DIR/info/exclude。排除文件中的模式会与 $GIT_COMMON_DIR/info/exclude 中的模式共同生效。

注意事项

gitignore 文件的目的是确保某些不由 Git 追踪的文件保持未追踪状态。

要停止追踪当前已追踪的文件,请使用 git rm --cached 将其从索引中删除。然后可以将文件名添加到 .gitignore 文件中,以防止该文件在后续提交中被重新引入。

当访问工作树中的 .gitignore 文件时,Git 不会跟踪符号链接。这保持了从索引或树中访问文件与从文件系统访问文件时行为的一致性。

示例

  • 模式 hello.* 匹配名称以 hello. 开头的任何文件或目录。如果只想将其限制在当前目录而非其子目录,可以在模式前加上斜杠,即 /hello.*;此时该模式匹配 hello.txthello.c,但不匹配 a/hello.java

  • 模式 foo/ 将匹配目录 foo 及其下的路径,但不会匹配常规文件或符号链接 foo(这与 Git 中路径规范的一般工作方式一致)。

  • 模式 doc/frotz/doc/frotz 在任何 .gitignore 文件中的效果相同。换句话说,如果模式中已经有了中间斜杠,前导斜杠就无关紧要了。

  • 模式 foo/* 匹配 foo/test.json(常规文件)、foo/bar(目录),但不匹配 foo/bar/hello.c(常规文件),因为模式中的星号不能匹配包含斜杠的 bar/hello.c

    $ git status
    [...]
    # Untracked files:
    [...]
    #       Documentation/foo.html
    #       Documentation/gitignore.html
    #       file.o
    #       lib.a
    #       src/internal.o
    [...]
    $ cat .git/info/exclude
    # ignore objects and archives, anywhere in the tree.
    *.[oa]
    $ cat Documentation/.gitignore
    # ignore generated html files,
    *.html
    # except foo.html which is maintained by hand
    !foo.html
    $ git status
    [...]
    # Untracked files:
    [...]
    #       Documentation/foo.html
    [...]

另一个例子

    $ cat .gitignore
    vmlinux*
    $ ls arch/foo/kernel/vm*
    arch/foo/kernel/vmlinux.lds.S
    $ echo '!/vmlinux*' >arch/foo/kernel/.gitignore

第二个 .gitignore 阻止 Git 忽略 arch/foo/kernel/vmlinux.lds.S

排除除特定目录 foo/bar 之外的所有内容的示例(注意 /* - 如果没有斜杠,通配符也会排除 foo/bar 内的所有内容)。

    $ cat .gitignore
    # exclude everything except directory foo/bar
    /*
    !/foo
    /foo/*
    !/foo/bar

GIT

Git[1] 套件的一部分