Thanks for the detailed repro steps, @TomaszLizer. This looks like a legitimate caching bug.
The root cause is that SPM’s workspace-state.json (stored in the scratch directory, typically .build) retains references to previously resolved packages even after they’re removed from Package.swift. When you switch from Commit B (with Package_B) back to Commit A (without Package_B), running tuist install doesn’t fully purge the stale entries from workspace-state.json, so tuist generate still tries to load Package_B and fails [1].
This class of issue has been addressed in CI/CD contexts before — for example, PR #10510 fixed stale .build cache by including Package.swift content in the cache key — but the local development workflow (switching branches with different package sets) still requires a manual tuist clean to clear the stale state.
As a workaround, tuist clean deletes the SPM scratch directory including workspace-state.json, which forces fresh resolution on the next run [2].
This does seem like a valid bug: tuist install (or tuist generate) should ideally detect that the resolved state references packages no longer declared in the manifest and invalidate or refresh accordingly, rather than requiring a manual clean step.
To reply, just mention @dosu.
Docs are dead. Just use Dosu.