Мы тоже искали решение подобной проблемы и пришли к тому, что меньше всего боли нам доставляет вот такой модифицированный gitflow:
- Код на продакшн заливается из ветки master.
- Код на тестовый сервер заливается из ветки develop.
- Все задачи делаются в отдельных feature-бранчах. Важно, что feature-бранчи ответвляются от master.
- Разработчик, завершив работу над задачей, мёржит ветку этой задачи в develop.
- Вмёрженные в develop задачи заливаются на тестовый сервер, где их сможет проверить тестировщик.
- Когда приходит время релиза, feature-бранчи для всех задач, которые должны быть включены в него и успешно протестированы, мёржатся в master.
- develop никогда не мёржат в master, потому что там может быть непроверенный код с багами.
Вот здесь мы описали этот подход более развернуто и пояснили некоторые тонкие моменты (например, что делать, если несколько задач логически связаны между собой).
Этот workflow подойдет не всем, многое зависит от сложившихся в команде процессов. Но в ситуации, которая описана в вопросе, он должен помочь (возможно, с небольшими изменениями).