Skip to content

.chezmoignore: Impossible to unignore patterns selectively on deeper levels #4636

@needleshaped

Description

@needleshaped

Describe the bug

Impossible to configure selective excludes (unignores) in .chezmoignore on subfolder levels.
This may be a bug either in code or documentation (e.g. missing example or statement it is impossible)

To reproduce

Simple use case: I want to manage *.sh and nothing else under selected folder - recursively, or at least with 1 level of subfolders (e.g. bin/devops, bin/windows, bin/azure-reports, etc)
Imagine, apart .exe there are temporary/intermediate files such as .json, .csv, etc.
Thus, whitelisting approach is cleaner, then blacklisting.

mkdir -p folder/subfolder
touch folder/file.{sh,exe}
touch folder/subfolder/file.{sh,exe}

# I'll show both config and result in same step
echo "# .chezmoignore:"; cat .chezmoiignore | grep folder;  echo "# chezmoi managed:"; chezmoi managed | grep folder

# .chezmoignore:
# chezmoi managed:
folder
folder/file.exe
folder/file.sh
folder/subfolder
folder/subfolder/file.exe
folder/subfolder/file.sh
# RESULT: as expected


# .chezmoignore:
folder/*
!folder/*.sh
# chezmoi managed:
folder
folder/file.sh
# RESULT: OK when 1 level deep


# .chezmoignore:
folder/*
!folder/*.sh
!folder/**/*.sh
# chezmoi managed:
folder
folder/file.sh
# RESULT: !folder/**/*.sh does NOT work


# .chezmoignore:
folder/*
!folder/*.sh
!folder/**/
!folder/**/*.sh
# chezmoi managed:
folder
folder/file.exe
folder/file.sh
folder/subfolder
folder/subfolder/file.exe
folder/subfolder/file.sh
# RESULT: attempt to allow all subfolder - does NOT work, unignores all contents even folder/file.exe!
# https://pkg.go.dev/github.com/bmatcuk/doublestar/v4#Match says /**/ must match directories!


# .chezmoignore:
folder/*
!folder/*.sh
!folder/subfolder/
!folder/**/*.sh
# chezmoi managed:
folder
folder/file.sh
folder/subfolder
folder/subfolder/file.exe
folder/subfolder/file.sh
# RESULT: changed !folder/**/ to specific folder name !folder/subfolder/. Now folder/file.exe is no longer unignored. But inside "subfolder" - still a problem


# .chezmoignore:
folder/*
!folder/*.sh
!folder/subfolder/
!folder/subfolder/*.sh
# chezmoi managed:
folder
folder/file.sh
folder/subfolder
folder/subfolder/file.exe
folder/subfolder/file.sh
# RESULT: !folder/**/*.sh > !folder/subfolder/*.sh did NOT help


# .chezmoignore:
folder/**
!folder/*.sh
!folder/subfolder/
!folder/subfolder/*.sh
# chezmoi managed:
# RESULT: folder/** prevents any unignore

Expected behavior

# chezmoi managed should report below, without including *.exe
folder
folder/file.sh
folder/subfolder
folder/subfolder/file.sh

Output of command with the --verbose flag

chezmoi --verbose managed does NOT produce any additional output

Output of chezmoi doctor

ESULT    CHECK                       MESSAGE
ok        version                     v2.65.0, commit 39e5ad1b8bb7c35a8a23aa1bdda5343224e77329, built at 2025-08-26T13:34:51Z, built by goreleaser
ok        latest-version              v2.65.0
ok        os-arch                     windows/amd64
ok        systeminfo                  Microsoft Windows 11 Pro (10.0.22631 N/A Build 22631)
ok        go-version                  go1.25.0 (gc)
ok        executable                  C:/scoop/apps/chezmoi/current/chezmoi.exe
ok        config-file                 found ~/.config/chezmoi/chezmoi.toml, last modified 2024-11-26T12:46:38+02:00
warning   source-dir                  ~/.local/share/chezmoi is a git working tree (dirty)
ok        suspicious-entries          no suspicious entries
warning   working-tree                ~/.local/share/chezmoi is a git working tree (dirty)
ok        dest-dir                    ~ is a directory
ok        cd-command                  found C:/scoop/apps/git/2.49.0/usr/bin/bash.exe
ok        cd-args                     bash
info      diff-command                not set
ok        edit-command                found ~/AppData/Local/Programs/Microsoft VS Code/bin/code.cmd
ok        edit-args                   code --wait
ok        git-command                 found C:/scoop/apps/git/2.49.0/mingw64/bin/git.exe, version 2.49.0
ok        merge-command               found C:/scoop/apps/git/2.49.0/usr/bin/vimdiff.exe
ok        shell-command               found C:/Windows/system32/cmd.exe
ok        shell-args                  'C:\\Windows\\system32\\cmd.exe'
info      age-command                 age not found in $PATH
ok        gpg-command                 found C:/scoop/apps/git/2.49.0/usr/bin/gpg.exe, version 2.4.7
info      pinentry-command            not set
info      1password-command           op not found in $PATH
info      bitwarden-command           bw not found in $PATH
info      bitwarden-secrets-command   bws not found in $PATH
info      dashlane-command            dcli not found in $PATH
info      doppler-command             doppler not found in $PATH
info      gopass-command              gopass not found in $PATH
info      keepassxc-command           keepassxc-cli not found in $PATH
info      keepassxc-db                not set
info      keeper-command              keeper not found in $PATH
info      lastpass-command            lpass not found in $PATH
info      pass-command                pass not found in $PATH
info      passhole-command            ph not found in $PATH
info      rbw-command                 rbw not found in $PATH
info      vault-command               vault not found in $PATH
info      secret-command              not set

Additional context

  1. Tested on Windows (Git Bash) only.
  2. I use mode = "symlink", but even with it commented chezmoi managed does not change produced results

Documentation consumed:

There is a side note, where 2 documentation contradict

Doublestar documentation says:

A doublestar (**) should appear surrounded by path separators such as /**/. A mid-pattern doublestar (**) behaves like bash's globstar option: a pattern such as path/to/**.txt would return the same results as path/to/*.txt. The pattern you're looking for is path/to/**/*.txt.

While .chezmoiignore page example states:

backups/** # ignore the contents of backups folder but not the folder itself

So which is true. By test above - .chezmoiignore page, but then ... should a link to doublestar doc be removed?

P.S. Created #4635, which falls under same category - unignore some deepr files in ignored directory (ps1 in $PROFILE) under Documents.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions