Search code examples
gitglobgitignore

Gitignore all non-matching a particular pattern


I've attempted to use the following in my .gitignore to no avail (files are being ignored, regardless of the !):

*
!(CODE_OF_CONDUCT|CONTRIBUTING|README).md
!.(editorconfig|github|gitignore|prettierrc|versionrc|vscode)
!(docs|example|LICENSE|src)
!(package|package-lock|(tsconfig.*)).json

Is there a way that I can get the above to work? That is, to match and exclude all except those that align with the described patterns.


Solution

  • I believe .gitignore uses filename globs, not regular expressions (and afaik also not extended globbing). As a result, the parentheses, the 'pipe symbol' (|), etc. have no special meaning and are interpreted as part of the filenames.

    Unfortunately, I don't think there is any way to express the or within the patterns. You need to do something along the lines of this (I did not include all original files):

    *
    !CODE_OF_CONDUCT.md
    !CONTRIBUTING.md
    !README.md
    !.editorconfig
    !.github
    !.gitignore
    !tsconfig.*.json
    

    If applicable, you can maybe group some files by common name parts, e.g.

    !.git*
    

    or by their extension, like

    !*.md
    

    and/or restrict the pattern to uppercase filenames

    ![ABCDEFGHIJKLMNOPQRSTUVWXYZ]*.md
    

    (Note that this is not the same as [A-Z]*, since standard glob sorts AaBbCc etc., so the latter means all upper- and lowercase characters except lowercase z).

    You could also 'group' by sub-directories, but that does not seem applicable in your case.

    See https://git-scm.com/docs/gitignore


    Edit: an indirect way of doing what you want, is using a more compact syntax when you generate the file (credits to @jthill):

    printf %s\\n \!{package,package-lock,tsconfig.*}.json >>.gitignore 
    

    However, this will not make the resulting file shorter.