This might not work for your use case, but because we try to merge to master frequently and not leave branches around for very long, we have had really good luck with this methodology.
We are using Azure DevOps as our build tool, and pushing builds into AppCenter.ms as our distribution tool for non-release builds. For release builds we push to the App Store directly.
AppCenter.ms allows you to create "Distribution Groups", which are basically a list of the email addresses you want to receive notifications when a new build is uploaded that "targets" that group. Each group has a unique GUID and if you use Azure DevOps and their .azure-pipelines.yml (or manually configure a build through the UI, though that is a very laborious process), you can use the AppCenter task with a condition that checks the branch name and deploys to specific group IDs based on the branch being built.
One of the things that makes this easier for us is we are using "enterprise distribution certificates", since these don't require individual device enrollment like ad hoc or developer certificates do. The other piece that could be important, if a user may install versions of the app from different groups you MUST have a different Bundle ID (and therefore another provisioning profile) for each version, otherwise they will clobber each other on the user's device. This is an Apple requirement (but Android has a similar unique bundle naming requirement).
In our case because these live in our Enterprise (not public AppStore) account, we have com.company.appname.test and com.company.appname.prodtest which for our purposes execute the same code, but they target different backend environments(URLs) for our APIs.