`dvc diff <rev>` reports all-deleted/0-added for outputs after splitting a single-dir `.dvc` into per-subfolder `.dvc` files (3.66.1)
Description
After refactoring a single dir-output .dvc (e.g. review.dvc tracking
review/) into multiple sub-folder .dvc files (review/<name>.dvc,
each with path: <name> relative to its parent), dvc diff HEAD
(i.e. HEAD vs workspace) reports every file under the refactored
subtree as deleted, with 0 added and 0 modified, even though:
dvc statusreports the workspace fully in sync.- The files all exist on disk at the expected paths.
- The dir-hash
.dircache files referenced by each new.dvcare present and enumerate correctly. - HEAD's
.dvcfiles are byte-identical to workspace's.dvcfiles (git statusclean). dvc diff HEAD HEAD(rev-to-rev) is correctly empty.dvc diff HEAD~1 HEAD(other rev-to-rev pairings) work correctly.dvc diff HEAD --targets <unaffected-subtree>works correctly.
The zero-added/zero-modified counts suggest the workspace-side enumeration is returning an empty file list for the refactored outputs, while the HEAD-side enumeration correctly expands the dir caches; the diff then attributes all HEAD-side files to "deleted."
Reproduction
Pre-refactor state:
project/
review.dvc # outs: [{path: review, md5: <dir-hash>}]
review/
after_cma_phase1/
clinician_files/
...Refactor (each commit does one):
# Remove the umbrella tracker, leaving files in place
dvc remove review.dvc
git rm review.dvc
# Track each subfolder individually
dvc add review/after_cma_phase1
dvc add review/clinician_files
dvc add review/edf_files
# ...
git add review/*.dvc
git commitEach new review/<name>.dvc looks like:
```yaml outs:
- md5: 69c24de62577c8e011842eaaa013ffc6.dir size: 1195692789 nfiles: 140 hash: md5 path: after_cma_phase1 ```
Then:
```bash $ dvc status Data and pipelines are up to date.
$ dvc diff HEAD HEAD
(empty, as expected)
$ dvc diff HEAD HEAD~1
(correct diff for the actual rev-to-rev change)
$ dvc diff HEAD --json | jq '{added, deleted, modified} | map_values(length)' { "added": 0, "deleted": 11957, "modified": 0 } ```
All 11,957 "deleted" paths still exist on disk and are correctly
listed inside their respective .dir cache files.
Things tried that did not help
dvc commit -f(no-op sincedvc statusis clean).- Running
dvc diff HEADfrom the subdirectory containing the refactored.dvcfiles. - Verifying every
.dircache file for each new sub-folder.dvcis present and well-formed.
Workarounds
dvc statusfor sync checks (authoritative; not affected).- Use commit-to-commit
dvc diff <rev1> <rev2>(not affected). - Scope HEAD-vs-workspace diffs to unaffected targets:
dvc diff HEAD --targets <other-target>(not affected).
Expected behavior
dvc diff HEAD with no workspace changes should report an empty
diff, matching dvc status.
Environment
``` DVC version: 3.66.1 (brew) CPython 3.14.2 Linux 6.18.28-1-lts (x86_64) glibc 2.43 ```
Repo layout: monorepo, DVC project lives in a subdirectory of the git repo (git toplevel and DVC root are not the same path). Remote: local FS path remote.
Source: treeverse/dvc