Make use of branches!
E.g.
Create a develop branch where you and your team usually works in, that can contain bugs, even unfinished code.
Then create a release branch from the develop branch. Now you can commit code into that branch to get the software into a stable state so that testers can work with it. Of course it's not allowed to merge the develop branch into the release branch once again.
As soon as your software in the release branch is stable and thoroughly tested, merge the release branch into the master branch and then back into the develop branch. After that, just delete the release branch.
Following this workflow...
- the master branch will only contain stable and tested code. Yay :)
- the release branch won't suffer from breaks the devs introduce in the develop branch during the lifetime of the release branch
- the develop branch will profit from stabilizing work that was done in the release branch. In fact, you should merge the release branch into the develop branch (not the other way!) as often as possible.