.forceignore does not seem to match patterns per .gitignore specification
Summary
.forceignore does not seem to match patterns per the .gitignore specification. When **/*.md is added to .forceignore, it also ignores .md-meta.xml files.
Steps To Reproduce
- Create a new empty repository:
sf project generate --name test
cd test
git init
git add . && git commit -m "initial commit"
- Add
**/*.mdto.forceignoreand.gitignore:echo '**/*.md' > .forceignore && echo '**/*.md' > .gitignore - Create a new test file:
mkdir -p force-app/main/default/customMetadata && touch force-app/main/default/customMetadata/test.md-meta.xml
- Notice that the test file is NOT excluded by git when running
git status - Auth to an org and pull a custom metadata file:
sf project retrieve start -m "CustomMetadata:Some.Record" - Notice that the file is not pulled:
Retrieving v64.0 metadata from <org> using the v64.0 SOAP API
✔ Preparing retrieve request 8ms
✔ Sending request to org 264ms
✔ Waiting for the org to respond 345ms
✔ Done 0ms
Status: Succeeded
Elapsed Time: 612ms
› Warning: Nothing retrieved
- Remove the pattern from
.forceignore:echo "" > .forceignore - Run the command again
- Notice that the file is pulled
Expected result
The CLI should not ignore .md-meta.xml files when **/*.md is added to .forceignore as this is not a correct pattern match (git does not do this).
Actual result
The CLI ignores .md-meta.xml files when **/*.md is added to .forceignore.
System Information
{
"architecture": "darwin-arm64",
"cliVersion": "@salesforce/cli/2.96.4",
"nodeVersion": "node-v22.17.0",
"osVersion": "Darwin 24.5.0",
"rootPath": "/Users/jonathanmorris/.local/share/sf/client/2.96.4-f8aa88b",
"shell": "zsh",
"pluginVersions": [
"@jedi/sf-jedi-plugin 4.0.0 (link) /Users/jonathanmorris/Documents/repos/sf-jedi-plugin",
"@muenzpraeger/sfdx-plugin 0.5.0 (user) published 1889 days ago (Tue May 12 2020)",
"@oclif/plugin-autocomplete 3.2.31 (core)",
"@oclif/plugin-commands 4.1.26 (core)",
"@oclif/plugin-help 6.2.29 (core)",
"@oclif/plugin-not-found 3.2.57 (core)",
"@oclif/plugin-plugins 5.4.43 (core)",
"@oclif/plugin-search 1.2.25 (core)",
"@oclif/plugin-update 4.6.45 (core)",
"@oclif/plugin-version 2.2.30 (core)",
"@oclif/plugin-warn-if-update-available 3.1.42 (core)",
"@oclif/plugin-which 3.2.37 (core)",
"@salesforce/cli 2.96.4 (core)",
"agent 1.23.2 (core)",
"apex 3.6.19 (core)",
"api 1.3.3 (core)",
"auth 3.7.4 (core)",
"code-analyzer 5.2.2 (user) published 20 days ago (Tue Jun 24 2025)",
"data 4.0.42 (core)",
"deploy-retrieve 3.22.27 (core)",
"dev 2.5.1 (user) published 237 days ago (Tue Nov 19 2024)",
"info 3.4.72 (core)",
"limits 3.3.58 (core)",
"marketplace 1.3.8 (core)",
"org 5.9.2 (core)",
"packaging 2.18.0 (core)",
"schema 3.3.69 (core)",
"settings 2.4.33 (core)",
"sobject 1.4.63 (core)",
"telemetry 3.6.45 (core)",
"templates 56.3.53 (core)",
"trust 3.7.107 (core)",
"user 3.6.27 (core)",
"@salesforce/sfdx-scanner 4.12.0 (user) published 76 days ago (Tue Apr 29 2025)",
"sfdmu 4.38.0 (user) published 197 days ago (Sun Dec 29 2024)"
]
}
Thank you for filing this issue. We appreciate your feedback and will review the issue as soon as possible. Remember, however, that GitHub isn't a mechanism for receiving support under any agreement or SLA. If you require immediate assistance, contact Salesforce Customer Support.
@jonathanmorris180 - interesting, thanks for reporting this. Is that file listed in the output of sf project list ignored?
looking at how we're passing the .forceignore into the ignore parser it almost seems like a bug for the library... I'll do some investigating
@WillieRuemmele It doesn't seem to. I agree that it's likely a bug in the ignore lib:
› Warning: @jedi/sf-jedi-plugin is a linked ESM module and cannot be auto-transpiled. Existing compiled source will be used instead.
No ignored files found in paths:
force-app
Unfortunately there doesn't seem to be a workaround either since adding this doesn't help:
**/*.md
# Try to NOT ignore md-meta.xml files...
!**/*.md-meta.xml
hey @jonathanmorris180 - would you mind creating an issue in the ignore library, you can link back here and we can keep this issue open
@WillieRuemmele I just tested out the ignore lib and it looks like it's not actually the source of the issue. See my minimal test here. If you run nvm use && node src/test.js, you'll see that ig.ignores(".abc/testing.md-meta.xml") returns false.
@jonathanmorris180 thank you for taking the time to try repro it in the library!
I'll mark this as a bug for now, repro:
- get a project with custom metadata (easy-spaces-lwc): https://github.com/trailheadapps/easy-spaces-lwc
- follow instruction in readme to create scratch and deploy project
- retrieve a custom metadata with/without the forceignore line:
✅ success
❌ failure
This issue has been linked to a new work item: W-19166508
it might be something with how the retrieve matches some paths, I don't see custom metadata being ignored with sf project list ignored with **/*.md in the forceignore.
@jonathanmorris180 , upon further investigation, we've determined that what was actually happening here is that the .md-meta.xml files were being returned from the Metadata API as .md files, and the .forceignore was being applied to the results of that, causing the files to be discarded. If you set your .forceignore file to be the following:
**/*.md
!**/customMetadata/*.md
then you should see the file not be excluded from results.
In our opinion, the true issue here is that the CLI was opaque in how it was choosing which files to ignore, so we've made it so that the --dev-debug flag will cause the CLI to explicitly list which files are being ignored. We'll let you know when that change goes live.
Thanks for your patience.