To start with, all systems that physically tie branches to directory layouts are just plain stupid. Code should be organized by the structure of the project. When you have to contort it to the needs of the VCS then something wrong.
The stream-based systems like AccuRev and ClearCase are closer to what VCS should be. But last time I checked AccuRev didn’t even have any support for build management. What’s the point of having the ability to easily move features from one stream to another if you can’t then build the damn thing? As for ClearCase, it is so buggy and temperamental you need a team just to babysit it.
The file system should be playing an active role too. Without any action by the developer, the file system and VCS should be tracking every revision to every file. And those revisions should remain available to me until I “checkpoint” the file and commit them to my private branch.
Check-ins should be based on features, not just change-sets. When I commit a set of files it should prompt me to strongly associate it with an issue or project number. Not just a soft-link like TFS does, I want a solid association where I can move the whole feature from one branch/stream to another branch/stream.
When pulling down code, I should be able to say “Get this branch/stream plus features X, Y, and Z”. I should then be able to say “Remove feature Y and recompile”. For this to work we also need to be able to indicate what the real dependencies are between features. Simply guessing that A requires B but not C because A and B have overlapping files is a good start, but we need the option to mark C as required as well.
Blind text comparisons aren’t enough, VCS systems need to deeply understand project and source files. When I add or remove a feature X from my local workspace, it should know how to update my project file accordingly. And it shouldn’t get confused just because project X and project Y both added the same file, but by chance put them in a different order in the project file.
Unit tests should never run on my machine. There should be a separate machine watching the changes on my machine and rerunning the applicable unit tests every time I change a file. When I notice something go red, the real-time versioning I mentioned in the third paragraph can be used to show me exactly what I did to break the test.