I'm surprised the obvious solution isn't already implemented universally by package managers: checkout the modules into a single directory, named as "[name]-[commit SHA]". You get all the benefits of the current system, with the added benefit that if A and B both turn out to want to check out C#1a029fb, then you only get one copy.
Eek, I didn't realize anyone thought it was a good idea for modules to be holding state inside themselves.
Simple-enough fix, though: drop an extra directory in there, call it "state", and have each state-container in that dir be named after the the hash of the dependency path you would have traversed to load it. Virtualize modifications to packages into those state-containers.
(This is also pretty much how Windows protects itself from programs that think keeping their state in the Program Files directory is a good idea.)
I'm not sure we are talking about the same thing: I was talking about runtime state (think: singleton instances). A directory wouldn't solve that problem.