In my personal experience, the workflow that works best for my team in the past was to have all developers share a single remote branch. For my team, we just happen to call this branch "master". Our branching strategy borrows ideas from this article: a-successful-git-branching-model. Just interchange "develop/master" branches from the article with "master/release" and you basically have my setup. It's the same, just labeled differently.
I basically let all our devs commit to master but with an added convention of only committing merges. All direct coding happens on topic branches. For quick fixes with only one changeset it's allowable to commit directly to master. But in general, the use of local topic branches are strongly encouraged.
Also, all commits to master must be pushed immediately otherwise differences would accumulate and make it harder to merge. In this way, the burden of resolving merges is the responsibility of the developer instead of the team leader or some automated software. This is the ideal situation since it is the person who develops the code who usually knows his own changes best.
If more than a single developer need to work on a single topic branch I allow all developers to push their own branches to remote under a specific path (in my case it was "shared/") so that others can pull and push from it.
As for the test server (CI server), it updates master and branches from it every test run. It's not strictly necessary to test on a new branch but I'm much more comfortable knowing some piece of automated script is not working directly on master.
If you're coming from svn, having constant small changes happening on a shared branch may seem a bit scary. Don't be scared, git is usually very good at resolving conflicts and 90% of the time a git merge
or git pull
wouldn't even trigger a conflict.
Lastly, make sure you instill in your developers the habbit of commit often, pull often. Small incremental changes actually helps git merge code better.