Git feature branching strategy allows unapproved 'tag along' features Context
Our current operations consists of three servers: QA is a playground for devs to try out new features; Platform is the live customer facing application; Mock is a copy of Platform and functions as a staging area for new releases to be tested before release to Platform.
Our branching strategy follows these three servers. There is a QA branch for the QA server, Mock branch for Mock, Master for Platform. When a new feature is requested, a feature branch is branched off Master to be developed on a devs local machine. Once the feature is complete, the feature branch is merged into the QA branch for testing/approval. When release time comes around, we pick out all the approved feature branches and merge them into the Mock branch for final release testing. After release testing the Mock branch is tagged as the next version and merged into Platform.
Symptom
The main issue that we have been dealing with using this strategy is that devs who finish a feature will accidentally branch off the newly finished (or sometimes still in progress) feature branch instead of the Master branch when moving on to the next feature. This means that when approved features are added into Mock for final release review, they can often carry along unapproved features as they sit in the same feature branch.
Question
Is there an automated way to go through each feature branch to check that no other feature branches are in its history since the last release tag? I can do this manually (which I do occasionally) but that becomes cumbersome. I can also make my own script to see if any branches share the same commit since the last git tag if such automation doesn't exist.
I am not trained in DevOps - if you see a glaring issue with this dev cycle please point it out to me!
Technically I guess something like this would print out any branchs between any particular branch and your master branch:
for hash in $(git log --format=%h master..); do if git branch --contains=$hash | grep -qv $(git name-rev HEAD | sed -e 's#HEAD ##g'); then git branch --contains=$hash | grep -v $(git name-rev HEAD | sed -e 's#HEAD ##g'); fi; done

But fundamentally there is probably an underlying problem here, I'm not intimate with your work flow or the teams you work with, but it seems unlikely to me that developers would accidentally create a new feature branch rooted on another feature branch unless they actually wanted some of the code in that other feature branch, perhaps to reuse in delivering whatever the new feature might be.
It seems that you might make a lot of improvement to your process quite quickly and easily by simply ensuring that the all features that are currently being worked on to completion are included in the next release and thus cN be merged into a pre-release branch as soon as they are approved. From there any branch taken from that pre-release branch should only contain features intended to be released,but it would mean that if a developer wrote code they thought was applicable to more than one problem,then they would almost immediately be able to reuse it once merged.
Although I'm not entirely sure that I've understood the issue you are facing, it seems to me that the existence of code in two branches isn't actually a problem, it's just code reuse. If one of those branches is pulled from the release then that's fine, the code that is being reused would still need to stay?