Short answer
Use some branch strategy and in your job do something like:
IF BRANCH endsWith RELEASE
deploy to testing
IF BRANCH endsWith SNAPSHOT
deploy to dev
IF BRANCH == MASTER
deploy to production
ETC ...
Detailed answer
When a developer perform a git push to Github, Bitbucket or Gitlab, these platforms send a Json to your continuous integration server(jenkis, travis,etc) with a lot of information related to the push event. Most important are:
- repository name
- target branch name: Branch who receive the git push
- commit message
- commit author

Then in your continuous integration server you must parse this Json to get important values. In jenkis there are several plugins like: Generic webhook, easy webhook plugin, github plugin, etc
After of values extraction you can apply simple or complex validations using branch name, commit message, commit author, etc. For instance:
- only master branch could be deployed to production environment
- only branch whose name ends with "snapshot" could be deployed to development environment: fix-issue-snapshot, feature-abc-snapshot, etc
- if commit message contains "WIP" it will mean that it is still in progress or development, then no deployment will be made.
- only push of team lead will be deployed
- if build , unit test and other validations are passed in the source code of feature-100-development branch, a new branch called feature-100-release will be created, then this branch will be deployed to testing environment. This *release branch is candidate to be deployed in production if Q&A Team does not detect any functional issue.
- any other automation flow from simple to complex.
Your imagination is your only limitation.
Useful links: