Skip to content

[bug] moon query changed-files ignores --head and mixes in local working tree / git status #2511

Description

@nicolasgere

Describe the bug

moon query changed-files --base <X> --head <Y> does not return the diff between X and Y. It silently drops --head and instead returns git diff <X> (one-arg, i.e. base → working tree) unioned with git status (local uncommitted state). Files touched in commits after --head, plus any local
modifications, show up as false positives. This breaks any commit-by-commit walk (release notes, per-commit "which projects were affected" gating, etc.).

Steps to reproduce

Repro repo: https://github.com/nicolasgere/moon-bug-repro — three linear commits: PARENT (root), MID (touches only pkg-a/a.txt), TIP (touches only pkg-b/b.txt), plus later README commits on main.

  1. Clone and install the pinned Moon version:
    git clone https://github.com/nicolasgere/moon-bug-repro.git
    cd moon-bug-repro
    proto install   # pins moon 2.2.3 via .prototools
  2. Resolve the three commits:
    MID="$(git rev-list -1 --grep='^commit2: only pkg-a' HEAD)"
    PARENT="$(git rev-parse "${MID}^")"
  3. Compare Git vs Moon for the PARENT..MID range:
    git diff --name-only "$PARENT" "$MID"
    # pkg-a/a.txt
    
    moon query changed-files --base "$PARENT" --head "$MID" -q | jq '.files'
    # [
    #   "pkg-b/b.txt",   <- false positive (only changed in TIP, after --head)
    #   "pkg-a/a.txt",
    #   "README.md"      <- false positive (only changed on main after TIP)
    # ]
  4. --remote produces the same wrong result.
  5. With MOON_LOG=trace, Moon parses the args correctly:
    moon_app::queries::changed_files  Against remote using base "<PARENT>" with head "<MID>"
    
    …but then issues a one-arg git diff (no <HEAD>):
    git diff --name-status --no-color --relative --ignore-submodules -z <PARENT>
    
    …followed by:
    moon_app::queries::changed_files  Against local index
    git status --porcelain --untracked-files --ignore-submodules -z
    
    So the effective query is git diff <BASE>git status, regardless of --head. Confirmed by running the same one-arg command directly — it returns exactly Moon's buggy file list.

Expected behavior

When both --base and --head are passed as explicit revisions, moon query changed-files should:

  1. Run git diff --name-status … <BASE> <HEAD> (two-arg) and return only the files in that tree-to-tree diff.
  2. Not consult git status / the local index — the user requested a diff between two SHAs, not a working-tree comparison.

i.e. the result should match git diff --name-only <BASE> <HEAD>.

Screenshots

N/A — terminal output included above.

Environment

  System:
    OS: macOS 26.3
    CPU: (18) arm64 Apple M5 Pro
    Memory: 461.39 MB / 48.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.14.0 - /Users/nicolas/.proto/tools/node/22.14.0/bin/node
    npm: 10.9.2 - /Users/nicolas/.proto/tools/node/22.14.0/bin/npm
    pnpm: 10.29.3 - /Users/nicolas/.proto/shims/pnpm
  Utilities:
    Git: 2.53.0 - /opt/homebrew/bin/git

moon: 2.2.3 (installed via proto 0.56.4)

Additional context

  • Affects any workflow that walks history commit-by-commit and pipes ranges into moon query changed-files or moon query projects --affected — release-notes generators and per-commit affected-project gating will silently report wrong results.
  • The bug shows up even with a clean working tree (no uncommitted edits); the false positives come from commits after --head, because git diff <BASE> compares base → working tree.
  • Suspected location: the changed-files query path in moon_app::queries::changed_files — the explicit---head branch appears to fall through to the same code as the implicit/local case.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions