...often there are untested changes waiting in the test branch which delays delivery of hot fixes for critical bugs in production.
Is there a method that allows for easy hot fixes and not introduce the risk of untested differences when having a separate release branch?
Yes, there is. The problem you've encountered is being caused by a bug in the workflow:
feature1 \
feature2 --> test --> release
hotfix1 /
As you've seen, if the features take time to test thoroughly, they act as a barrier for getting the hot fix through the pipeline. The takeaway there is that if you need to get a release out quickly, there shouldn't be anything in the release pipeline that isn't very close to being ready.
You can prevent that by moving the barrier ahead of the release part of the pipeline so that any delays in testing a change stay with the change:
feature1 --> feature1-test \
feature2 --> feature2-test --> release-test --> release
hotfix1 --> hotfix1-test /
When a change is finished, it goes into a separate branch where it is tested. As long as testing is underway, all work on that change happens between the two branches. After testing has approved it, the tested code is merged into a pre-release testing branch where the full test battery is run once more before release. (In theory, this should be a formality and a non-event; I'll explain why later.) This means you can take a long as you want testing feature1
without delaying feature2
or the hotfix
.
One important thing that's frequently overlooked is feedback. Whenever a release happens, that code needs to be merged into all branches where development and testing are being done. If hotfix1
breaks feature1
, you want to find that out in feature1-test
so it can be fixed there and won't stand in the way of a release containing hotfix2
. If the feature integrates the released changes early, there should be fewer surprises in release-test
. This arrangement allows you to treat hotfixes and features the same way from a development perspective and leaves the decision whether to subject a hotfix to the full battery of testing or fast-track it a matter of QA policy. The workflow is the same no matter what, and there isn't a quick branch/merge from/to the release
branch.
NB: What's described here is a bit of an oversimplification because it doesn't take into account something in feature1
breaking something in feature2
. This arrangement can be used in more-complex structures where release-test
becomes integration-test
and that feeds release-test
.