-
Notifications
You must be signed in to change notification settings - Fork 49
Description
Describe the bug
The "git" walker will walk - and thus include and scan/format - files NOT known to git, e.g. untracked files. This seems quite counterintuitive to me, I expect a walker named "git" to only include files known to git (committed or staged). If I needed treefmt to walk files regardless of their relation to git, that seems to be what the "filesystem" walker is intended for, or I would explicitly run treefmt path/to/file.
This behaviour was introduced in #557 / #560 and even announced as a "feature" in v2.2.0.
In #557, the user described adding a file to the git index (via git add) but not yet committed ("staged" in Git terms), and opined that the file they had just "git add"ed was not included in treefmt via git ls-files. I'm unsure what the user's original issue was because I'm unable to reproduce their described behaviour they experienced; in short, a staged file - regardless of if it's ever been committed - DOES already appear in the default and original git ls-files output. I even tested with treefmt 2.1.1, the release prior to the inclusion of #560 and confirmed that the staged file IS processed by treefmt as #557 asserted it should have been [but wasn't].
brycec:/tmp/porcupines $ /tmp/treefmt --version
treefmt v2.1.1$
brycec:/tmp/porcupines $ /tmp/treefmt -vv
2025/06/06 11:01:58 INFO using config file: /tmp/porcupines/treefmt.toml
DEBU walk | git: processing file: /tmp/porcupines/.gitignore
DEBU walk | git: processing file: /tmp/porcupines/Committed
DEBU walk | git: processing file: /tmp/porcupines/Staged
DEBU walk | cache: read 3 files from delegate
DEBU formatter | mylanguage: match: /tmp/porcupines/.gitignore
DEBU formatters signature for key mylanguage: 3cdb31578adf1058d99e43f48d2083f8
DEBU formatter | mylanguage: match: /tmp/porcupines/Committed
DEBU formatter | mylanguage: match: /tmp/porcupines/Staged
traversed 3 files
emitted 3 files for processing
formatted 0 files (0 changed) in 11msIn addition, the addition of --others in #560 actually caused the regression reported by #565. --exclude-standard would not be needed if --others was not passed to git ls-files
Here is an example of git ls-files that confirms that staged (git add) files are included in the output by default, and that .gitignore files are also excluded from the output by default.
# Create a simple git repo with some files in varying Git states
brycec:~ $ mkdir /tmp/porcupines
brycec:/tmp $ cd /tmp/porcupines
brycec:/tmp/porcupines $ git init
Initialized empty Git repository in /tmp/porcupines/.git/
brycec:/tmp/porcupines $ touch Untracked Staged Committed Ignored
brycec:/tmp/porcupines $ git add Committed
brycec:/tmp/porcupines $ git commit -m "Committed a file"
[main (root-commit) 1f5856f] Committed a file
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 Committed
brycec:/tmp/porcupines $ echo IgnoredFile > .gitignore
brycec:/tmp/porcupines $ git add .gitignore
brycec:/tmp/porcupines $ git add Staged
# As of v2.1.1
brycec:/tmp/porcupines $ git ls-files
.gitignore
Committed
Staged
# As of #560 / 9662ee657c9e6c52f1758b13da98ad2391304c48, v2.2.0
brycec:/tmp/porcupines $ git ls-files --cached --others
IgnoredFile
Untracked
.gitignore
Committed
Staged
# As of #565 / cca79a8385c339b492e00fea6125a7056758b5db, v2.2.1
brycec:/tmp/porcupines $ git ls-files --cached --others --exclude-standard
Untracked
.gitignore
Committed
StagedTo Reproduce
Steps to reproduce the behavior:
- Start with the above sample git repository.
- And the following treefmt.toml
[formatter.mylanguage] command = "echo" options = [] includes = [ "*" ] excludes = [] priority = 0
treefmt -vv- Observe that treefmt ran the "mylanguage" formatter against untracked files
Untracked,treefmt.tomlbrycec:/tmp/porcupines $ /tmp/treefmt --version treefmt v2.3.1$ brycec:/tmp/porcupines $ /tmp/treefmt --init Generated treefmt.toml. Now it's your turn to edit it. brycec:/tmp/porcupines $ grep -E '^[^# ]' treefmt.toml walk = "git" [formatter.mylanguage] command = "touch" options = [] includes = [ "*" ] excludes = [] priority = 0 brycec:/tmp/porcupines $ /tmp/treefmt -vv INFO config: no tree root specified INFO config: attempting to resolve tree root using git: git rev-parse --show-toplevel DEBU tree-root-cmd | stdout: /tmp/porcupines INFO config: tree root: /tmp/porcupines DEBU Resolving path '/tmp/porcupines': git DEBU walk | git: processing file: /tmp/porcupines/Untracked DEBU walk | git: processing file: /tmp/porcupines/treefmt.toml DEBU walk | git: processing file: /tmp/porcupines/.gitignore DEBU walk | git: processing file: /tmp/porcupines/Committed DEBU walk | git: processing file: /tmp/porcupines/Staged DEBU walk | cache: read 5 files from delegate DEBU read 5 files DEBU formatter | mylanguage: match: /tmp/porcupines/Untracked DEBU formatters signature for key mylanguage: 3cdb31578adf1058d99e43f48d2083f8 DEBU formatter | mylanguage: match: /tmp/porcupines/treefmt.toml DEBU formatter | mylanguage: match: /tmp/porcupines/.gitignore DEBU formatter | mylanguage: match: /tmp/porcupines/Committed DEBU formatter | mylanguage: match: /tmp/porcupines/Staged DEBU formatter | mylanguage: executing: /usr/bin/touch Untracked treefmt.toml .gitignore Committed Staged INFO formatter | mylanguage: 5 file(s) processed in 1.55886ms DEBU file has changed path=Untracked prev_size=0 prev_mod_time="2025-06-06 10:18:35 -0700 PDT" current_size=0 current_mod_time="2025-06-06 10:50:59 -0700 PDT" DEBU file has changed path=treefmt.toml prev_size=2196 prev_mod_time="2025-06-06 10:50:57 -0700 PDT" current_size=2196 current_mod_time="2025-06-06 10:50:59 -0700 PDT" DEBU file has changed path=.gitignore prev_size=12 prev_mod_time="2025-06-06 10:23:13 -0700 PDT" current_size=12 current_mod_time="2025-06-06 10:50:59 -0700 PDT" DEBU file has changed path=Committed prev_size=0 prev_mod_time="2025-06-06 10:18:43 -0700 PDT" current_size=0 current_mod_time="2025-06-06 10:50:59 -0700 PDT" DEBU file has changed path=Staged prev_size=0 prev_mod_time="2025-06-06 10:18:41 -0700 PDT" current_size=0 current_mod_time="2025-06-06 10:50:59 -0700 PDT" traversed 5 files emitted 5 files for processing formatted 5 files (5 changed) in 16ms DEBU no more files to read
Expected behavior
My expectation is that, with walk = "git", only the files included in git ls-files (.gitignore, Committed, and Staged in the above example) will be processed; files Untracked and treefmt.toml would NOT be considered by treefmt. Only "3" files should have been processed/traversed/formatted above.
I propose that the fix is to revert to using git ls-files without any further switches, and documentation that clearly states that the git walker will only include files known to git, including staged files, and observes .gitignore exclusions; if the user needs for treefmt to scan untracked files or ignored files, they should use the "filesystem" walker or pass those files directly to treefmt as arguments.
System information
Observed and confirmed on multiple Linux systems including ArchLinux and NixOS 25.05. treefmt is version 2.3.1.