Thanks, I appreciate your trying to understand my question.
Separate branches don't work because tags are associated with repos and not branches. A fork would be a better, but is heavyweight and still has some of the problems described below.
More, specifically for private repositories, I mean a private spec repo for publishing the pod specifications. Private spec repo details are described here. And that is indicative of one of the key differences between CocoaPods and SPM. In CocoaPods, specifications are managed separately from the source that is specified. The podspec may or not be in the same repo as the source; the one that identifies a release is the one that is published to the trunk spec repository; and the spec itself specifies the git tag for identifying the release source.
Consider three packages A is at 1.0 which depends on 2.0 B which depends on 3.0 of C. In CocoaPods, when I want to update to A 1.1 depending on B 2.1 depending on C 3.1, I can update all three repos, tag the repo and push the podspecs to a private repo to enable the three packages to be tested together by any clients with access to the repo. When I'm ready to publish the release, I can push the three podspecs to CocoaPods trunk without needing to touch the A, B, and C repos.
I cannot do the same thing in SPM, because as soon as I tag 3.1 on repo C, it gets installed to all B clients (assuming B specifies "3.0.0" .. < "4.0.0" for its C dependency). Therefore, in order to do integration testing of B and C, I need to change B's Package.swift to something other than its version specification, and similarly for A. Then, when I'm done testing, I need to change it back and release from different git hashes than what I tested.