What is usually done is:
- you push on the testing server on a test branch
- when you are ready, you merge that test branch to master and push on the testing server on master.
- you have a post-receive hook which, on push on master branch, will push to the bare repo on prod (as illustrated in "How to do branching approach for multiple sites?").
- you have a post receive hook on prod repo which will checkout the working tree in the live folder upon reception of the new commits. (as explained in "git push origin master not pushing the files").