You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Deduplicate deletes git branch refs and reflogs because .git folders under the root are scanned as ordinary files #192
FileScanner.ScanForFiles (FileDeduplicator/FileScanner.cs:71-103) walks every file under the root using WalkOptions (:38-43). That walk skips only reparse points; nothing excludes version-control metadata.
Inside .git, many small files have identical content:
every loose branch ref that points at the same commit (41 bytes, <sha>\n)
logs/HEAD and logs/refs/heads/<current branch>
the reflogs of branches created from the same commit
DuplicateScan.Run (DuplicateScan.cs:49) groups these files as duplicates. Deduplicator.DeleteDuplicates (Deduplicator.cs:138-191) then keeps the file with the shortest name (OrderByPreference, :123-124) and deletes the rest. On a refs directory, that deletes branches.
It reports "Deleted 4 file(s). Reclaimed 345 B" and exits 0. Afterwards git branch lists only main. If those branches had diverged, their tips would now be reachable only through the reflogs, and the same run deleted those too.
The normal use is pointing the tool at a projects folder, a home directory or a backup drive. That hits every repository in the tree, silently deleting branches to reclaim a few hundred bytes per repository.
Skip version-control metadata directories during the walk: at least .git, .svn, .hg and .bzr.
Use a directory filter on the enumeration, not a substring match on paths.
A .gitfile (a worktree or submodule pointer) needs no special handling.
Mention the exclusion in the README, next to the empty-file rule.
Add a test with a temp tree containing .git/refs/heads/{a,b} with identical content, plus a real duplicate pair outside .git. Scan, DryRun and Deduplicate should report and delete only the pair outside .git, and leave the .git files untouched.
Priority: Critical. The normal use of the tool (pointing it at a projects folder, home directory or backup drive) silently deletes branch refs and reflogs in every repository under the root and exits 0. Diverged branch tips become unreachable and are lost at the next git gc, to save a few hundred bytes.
Area / suggested assignee:FileScanner.ScanForFiles / WalkOptions (FileScanner.cs:38-103). Owner: @matt-edmondson
Next step: prune .git, .svn, .hg and .bzr directories in the enumeration (not a path-substring filter), note the exclusion in the README, and add the .git/refs/heads/{a,b} + real-duplicate test from the issue. Worth landing ahead of other FileDeduplicator work and cutting a patch release.
Activity
matt-edmondson commentedon Oct 20, 2026
Triage
git gc, to save a few hundred bytes.FileScanner.ScanForFiles/WalkOptions(FileScanner.cs:38-103). Owner: @matt-edmondsondedup dedupedescends into.gitand deletes branch refs and reflogs that happen to hold the same commit SHA KtsuTools#222 (dedup dedupedescends into.git), still unfixed. Fix both with the same directory-pruning rule so the two tools don't drift. Related to Deduplicate removes one name of a hardlinked duplicate and reports the space as reclaimed, but frees nothing and the next Scan finds the same duplicate again #190 (hardlink handling), which is waiting on PR Count a hardlinked file once in Stats [patch] #191; this fix is independent of it. No open PR covers this..git,.svn,.hgand.bzrdirectories in the enumeration (not a path-substring filter), note the exclusion in the README, and add the.git/refs/heads/{a,b}+ real-duplicate test from the issue. Worth landing ahead of other FileDeduplicator work and cutting a patch release.Generated by Claude Code