
When configuring path-based triggers or excludes in Azure DevOps pipelines, the pattern you use can have a significant impact on which files or folders will trigger a build. There are subtle but important differences between the patterns docs, docs/, docs/** and docs/**/*.
And I often see wrong trigger definitions.
Pattern Overview
docs
Matches only the file or folder named docs at the root. Does not match files inside the folder. Rarely useful for excludes.
docs(folder itself) → excludeddocs/readme.md→ not excludeddocs/guide/intro.md→ not excluded
docs/
Matches the folder named docs and everything inside it, recursively. Equivalent to docs/** in most cases.
docs/readme.md→ excludeddocs/guide/intro.md→ excludeddocs/assets/image.png→ excludeddocs/guide/advanced/usage.md→ excludeddocs/(folder itself) → excluded
docs/**
Matches all files and folders under docs at any depth, including the folder itself. Excludes everything recursively.
docs/readme.md→ excludeddocs/guide/intro.md→ excludeddocs/assets/image.png→ excludeddocs/guide/advanced/usage.md→ excludeddocs/(folder itself) → excluded
docs/**/*
Matches all files (not folders) at any depth under docs. Excludes all files recursively, but not the folder itself.
docs/readme.md→ excludeddocs/guide/intro.md→ excludeddocs/assets/image.png→ excludeddocs/guide/advanced/usage.md→ excludeddocs/(folder creation/deletion) → not excluded
Summary Table
| Changed File/Folder | Excluded by docs | Excluded by docs/ | Excluded by docs/** | Excluded by docs/**/* |
|---|---|---|---|---|
| docs | Yes | Yes | Yes | No |
| docs/readme.md | No | Yes | Yes | Yes |
| docs/guide/intro.md | No | Yes | Yes | Yes |
| docs/assets/image.png | No | Yes | Yes | Yes |
| docs/guide/advanced/usage.md | No | Yes | Yes | Yes |
Recommendation
Use docs/ or docs/** if you want to exclude all changes within the docs folder and any subfolders, including folder changes. Use docs/**/* if you want to exclude all files at any depth, but not changes to the folder itself. The plain docs pattern is rarely useful for excludes.
Example YAML
1trigger:
2 branches:
3 include:
4 - main
5 paths:
6 exclude:
7 - docs/** # Excludes all changes in docs and subfolders (including folders)
8 # - docs/**/* # Excludes all files in docs and subfolders, but not the folder itself

Comments