Skip to content

Clean by deleting bin and obj, not by asking dotnet to - #43

Merged
revtex merged 1 commit into
mainfrom
clean-deletes-bin-obj
Aug 29, 2026
Merged

Clean by deleting bin and obj, not by asking dotnet to#43
revtex merged 1 commit into
mainfrom
clean-deletes-bin-obj

Conversation

@revtex

@revtex revtex commented Aug 29, 2026

Copy link
Copy Markdown
Owner

dotnet clean removes what the configuration and target framework you name would have produced. Everything else it leaves, and there was a great deal of it — 645 MB, found while clearing the working tree:

Residue Size Why dotnet clean never reached it
net10.0-windows/ output (24 dirs) 485 MB Stranded when the app retargeted to Windows 11 on 2026-08-14. No build names that TFM any more, so nothing cleans it.
obj/{s,scratch,scratch2,scratchbuild}/ (9 dirs) 183 MB Builds that redirected BaseOutputPath to get past a locked DLL.
spike/ The project was deleted in Phase 2; an empty obj/ shell outlived it.
78 × *_wpftmp.csproj.nuget.* 1.6 MB Stale WPF temp-project restore stubs.

None of it appeared in git status, which is why it lasted. [Bb]in/ and [Oo]bj/ are unanchored, so they match at any depth and the residue was ignored from the moment it was written. That is the right rule — the variant it doesn't cover, an output directory at the project root, shows up as untracked and gets noticed the same day — but it does mean nothing was ever going to point at this.

What changed

-Clean now deletes bin/ and obj/ beside every project in the solution and reports what it freed:

Cleaning (every configuration and target framework)...
  removed 12 folder(s), 181 MB
  • It ignores -Configuration. The whole value is in taking the configurations you are not building — those are the ones nothing else will touch.
  • It walks the .csproj files rather than sweeping the tree recursively, so it cannot wander into .git, .vs, or a vendored folder that happens to contain a bin.
  • A locked folder names the likely cause. A running Offstream holds its own binaries open, and Windows reports that as a file it cannot access — true, unhelpful, and the same message you get for half a dozen unrelated problems. Worth a line, because this is also where the obj/scratch* trees came from: redirecting the output path gets past the lock and quietly leaves the copy behind.

Verification

  • Orphan removal, tested directly — planted a bin/Release/net10.0-windows/ and an obj/scratch9/, the two classes dotnet clean structurally cannot reach. Both removed, 0 survivors.
  • Lock path — held an open handle on Offstream.Core.dll from a separate process and confirmed the guidance fires rather than the raw Windows message.
  • build.ps1 -Clean -Test from an empty tree — Build succeeded, 0 warnings, 0 errors; 924 Core + 204 UI passing, 0 failures.
  • build.ps1 -VerifyFormat — exit 0.

Docs

CHANGELOG.md under [Unreleased]. The README's -Clean help line, plus its test count, which said 1,089 against a suite of 1,128 — corrected while in the file rather than left to drift further. The plan gets the finding beside the one about build.ps1 holding a second copy of the TFM, since they are the same lesson from opposite ends: changing the TFM invalidates paths that no longer appear anywhere in the build, and the ones already on disk have nothing left that knows their name.

🤖 Generated with Claude Code

`dotnet clean` removes what the configuration and target framework you
name would have produced. Everything else it leaves, and there was a
great deal of it: 485 MB of `net10.0-windows` output stranded when the
app retargeted to Windows 11 a fortnight ago, and 183 MB of
`obj\scratch*` trees from builds that had redirected their output path
to get around a locked DLL. Two thirds of a gigabyte that no build would
ever look at again, surviving every clean anyone ran.

None of it appeared in `git status`, which is why it lasted. `[Oo]bj/`
and `[Bb]in/` are unanchored, so they match at any depth and the residue
was ignored from the moment it was written. That is the right rule -
the variant it does not cover, an output directory at the project root,
shows up as untracked and gets noticed the same day - but it does mean
nothing was ever going to point at this.

So `-Clean` deletes both folders beside every project in the solution
and says what it freed. It ignores `-Configuration` deliberately: the
whole value is in taking the configurations you are not building, since
those are the ones nothing else will touch. It walks the `.csproj` files
rather than sweeping the tree recursively, so it cannot wander into
`.git`, `.vs`, or a vendored folder that happens to contain a `bin`.

Failing to delete a folder now names the likely cause. A running
Offstream holds its own binaries open, and Windows reports that as a
file it cannot access - true, unhelpful, and the same message you get
for half a dozen unrelated problems. Worth spending a line on, because
this is also where the `obj\scratch*` trees came from: redirecting the
output path gets past the lock, and quietly leaves the copy behind.

The plan gets the finding beside the one about `build.ps1` holding a
second copy of the TFM, since they are the same lesson from opposite
ends - changing the TFM invalidates paths that no longer appear anywhere
in the build, and the ones already on disk have nothing left that knows
their name.

The README's test count said 1,089 and the suite is 1,128. Corrected
while in the file rather than left to drift further.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@revtex
revtex merged commit 9d65f9b into main Aug 29, 2026
6 checks passed
@revtex
revtex deleted the clean-deletes-bin-obj branch August 29, 2026 15:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant