Skip to content

feat(ignore): auto-load .stglobalignore as shared folder ignore patterns#10742

Open
grantstephens wants to merge 1 commit into
syncthing:mainfrom
grantstephens:feat/global-stignore
Open

feat(ignore): auto-load .stglobalignore as shared folder ignore patterns#10742
grantstephens wants to merge 1 commit into
syncthing:mainfrom
grantstephens:feat/global-stignore

Conversation

@grantstephens

@grantstephens grantstephens commented Jun 13, 2026

Copy link
Copy Markdown

Purpose

Implements automatic loading of a .stglobalignore file from the folder root, appending its patterns after the local .stignore patterns.

This addresses a long-standing pain point: when a folder syncs to a new host, .stignore is not synced (by design), so users must manually recreate their ignore patterns on every new device. The common workaround is to put a #include .stglobalignore line in each .stignore, but that still requires per-device setup.

With this change:

  • Shared ignore patterns go in .stglobalignore in the folder root
  • .stglobalignore syncs between devices like any normal file (it is not in the IsInternal list)
  • No per-device configuration is needed — the file is picked up automatically on load

Precedence: Local .stignore patterns are evaluated first, so they can override global ones. A negation in .stignore overrides an ignore in .stglobalignore, and vice versa.

Change detection: .stglobalignore is registered with the ChangeDetector during load, so modifications trigger a reload on the next scan — identical to how #include files are tracked.

Missing file: If .stglobalignore does not exist the folder loads normally with no error.

Closes #7311
Related: #10208, #2353

Implementation notes

The global file loading lives entirely in Load(), keeping parseLocked() as a pure "parse this reader → apply state" function. A new applyPatterns() helper was extracted to hold the hash-comparison and state-setting logic, used by both paths.

Two named constants are introduced:

  • IgnoreFile = ".stignore" (exported — callers in model.go etc. can migrate over time)
  • globalIgnoreFile = ".stglobalignore" (unexported, single definition)

Testing

Four new tests in lib/ignore/ignore_test.go:

  • TestGlobalIgnore/LocalNegationBeatsGlobalIgnore — global ignores .git/**, local negates .git/config; verifies local wins
  • TestGlobalIgnore/LocalIgnoreBeatsGlobalNegation — local ignores a file that global tries to un-ignore; verifies local wins
  • TestGlobalIgnoreMissing — no .stglobalignore present; verifies clean load with no error
  • TestGlobalIgnoreChangeDetection — modifies .stglobalignore with a future modtime; verifies patterns reload correctly

Run with:

go test github.com/syncthing/syncthing/lib/ignore -run TestGlobalIgnore -v

Screenshots

No GUI changes.

Documentation

Docs PR: syncthing/docs#1016

Authorship

Note: this PR was developed with AI assistance (Claude). The implementation was designed, reviewed, and is understood by me as the submitter. I am responsible for its correctness and accept the DCO accordingly.

@st-review st-review added the rep/positive Author reputation signal is positive label Jun 13, 2026
@github-actions github-actions Bot added the enhancement New features or improvements of some kind, as opposed to a problem (bug) label Jun 13, 2026
@grantstephens grantstephens force-pushed the feat/global-stignore branch from 97f0968 to ecbb1a7 Compare June 13, 2026 04:43
When a folder is loaded, patterns from a .stglobalignore file in the
folder root are automatically appended after the local .stignore
patterns. Because local patterns are evaluated first, .stignore can
override global patterns (e.g. a !.git/config negation beats a .git/**
ignore in .stglobalignore).

Unlike .stignore, .stglobalignore is not listed as an internal file, so
Syncthing syncs it between devices like any other file. This means
shared ignore patterns only need to be written once and are propagated
automatically when the folder syncs to a new host — without any manual
setup on each device.

Change detection is handled automatically: .stglobalignore is registered
with the ChangeDetector during parse, so any modification triggers a
pattern reload on the next scan.

Closes syncthing#7311
Related: syncthing#10208, syncthing#2353

Signed-off-by: Grant Stephens <grant@stephens.co.za>
@grantstephens grantstephens force-pushed the feat/global-stignore branch from ecbb1a7 to d99aec4 Compare June 13, 2026 04:46
grantstephens added a commit to grantstephens/docs that referenced this pull request Jun 13, 2026
Adds description and versionadded note for the new .stglobalignore
file, which is synced between devices and automatically loaded
alongside .stignore.

Related: syncthing/syncthing#10742
Closes syncthing/syncthing#7311

Signed-off-by: Grant Stephens <grant@stephens.co.za>
@grantstephens grantstephens marked this pull request as ready for review June 13, 2026 04:48
@acolomb

acolomb commented Jun 13, 2026

Copy link
Copy Markdown
Member

How can the user control the ordering of ignore patterns? If there are global patterns for a selective sync:

!/foo
*

And the user applies the same principle locally:

!/bar
*

Then it's not obvious that the global patterns are effectively dead. With the current solution (explicit #include .stglobalignore) you can at least see what gets applied by looking at one file alone or the in-GUI pattern editor.

Another pain point I see is that the user cannot control what ignores are applied locally. Any other device can push ignore patterns to them and it's not even possible to get around them. This type of not being in charge of your own Syncthing instance goes against Syncthing's current philosophy.

So from my side, clear NAK.

The workaround if you don't want to remember adding the include for every new folder already exists. Put that line in the folder defaults configuration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New features or improvements of some kind, as opposed to a problem (bug) rep/positive Author reputation signal is positive

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Could we have a .stsharedignore file that gets synchronized between all the devices?

3 participants