Can't comment so - the strategy with different levels of branches (Pascal's answer) is great. However, I think one thing you would want to clear up is whether "commit" equals "release". It shouldn't.
What we have been doing with a single team per project was that developers commit when ready, however the commit must not break unit tests harness (similar to "unit tested" policy in the workflow from Pascal's excellent answer). We have a test server running straight from the repository and updating after each commit (we do web apps - this is equal to having a build of your software every commit or every day). Everyone can access that server, including the POs and stakeholders - in fact anyone who wants can play with it and provide feedback.
Now, code reviews are assigned as explicit work on the sprint backlog to each item. Items that have not been through code reviews are not considered completed and are not part of the shippable increment that is released at the sprint's end.
In this scenario "committing" means sending your code to the repo. Your code will be visible to others, it will be also visible working on the test server (if it won't break something). The psychological barrier is much lower than if committing meant sending something that is considered releasable. Still, each developer knows their code won't be really released before a code review and they will have to wear a funny-looking hat for the rest of the day if they send a commit that will break unit tests.
As for code reviews taking time - well, this is time well spent, time invested towards higher quality of the product. Well worth it.