Not really. You just need to break out a new version when you put out a breaking change. This can mean anything between duplicating the code that implements your interface to then apply a change and checking a version flag when invoking an operation to determine which version to run.
Do you struggle to not break your code? To me it's like the main responsibility of any developer, isn't it?
> Why would you try to preserve contracts if you're in fact in control of all producers and consumers?
Because you clearly aren't in control, if you feel compelled to dump anything and everything in the same repository to try to prevent things from breaking.
Also, as others have pointed out, storing code in the same repository gives you no assurance that all your services will be deployed at the same exact moment in time. Consider for example multi-region deployments, or even deployments to multiple availability zones. Those aren't atomic. Why does anyone believe that storing all code in the same repository is enough to make these operations atomic?