What's the practice to perform a releasing with Git? I'm using GitLab CE with Maven project, and try to follow the Environment branches with GitLab flow and The 11 Rules of GitLab Flow 

The step for releasing is as the following: - 

feature   +---   +---          +---
         /    \ /    \        /    \
master  + ---- + ---- + ---- + ---- +  
                        \            \
qa-tmp (chage ver to RC) +---         + --- 
                             \             \
qa      + ------------------- + ---------- +
                             (v1.0-RC1)   (v1.1-RC1)
                              \            \    
prod-tmp (chage ver to final)  +---         + ---
                                   \             \
prod    + ------------------------ + ------------ +
                                 (v1.0)         (v1.1)



Create a feature branch and merge into the master so that it is ready to be released
Create the qa-tmp branch e.g. release-v1.0-RC1 from master

2.1 Update the pom version to 1.0-RC1

2.2 Merge the release-v1.0-RC1 to qa

2.3 Tag v1.0-RC1 from merged qa branch.
When it pass the QA, create prod-tmp branch e.g. release-v1.0 from tag v1.0-RC1

3.1 Update the pom version to 1.0

3.2 Merge the release-v1.0 to prod

3.3 Tag v1.0 from merged prod branch

3.4 Bump master to version 1.1-SNAPSHOT
Develop the version 1.1-SNAPSHOT in the features &amp; master when it is ready to be released, repeat the step 2 and 3.


The trouble is since the version is changed during merging the qa branch and prod branch, when I perform a next release there is a merge conflict for the version inside the pom. This cause me to resolve this conflict manually.

I'm not sure if I'm doing something wrong or misunderstanding about the releasing procedure or not. 

Furthermore, do we have any practice to make this releasing to be an automation, e.g. via script? 

Could you please help to advise?
Consider to substitute the version in POM by the git describe upon build without hardcoding the version in your repository, you could do this with e.g. sed from below version_slug.

export git_version=`git describe --tags --always`
export version_slug="$(sed s/-/\./g &lt;&lt;&lt;$git_version)"


and then substitute the version_slug in pom.

In that way for each commit and/or tag in gitlab, you'll create a new version, with out actually changing the repository. 

this is what i did for a ruby project: jekyll-plantuml-url, where the version is not coded in the source, but is set upon build, and after testing deployed as the git tag.

  script:
   - bundle install
   - rake set_git_tag
   - rake
   - gem build jekyll-plantuml-url.gemspec


Furthermore don't understand the need of all those branches, with CI/CD we continuously build, test and deploy, that means before accepting a merge to master you have a deployment for QA to do the testing, code review, functional testing ...etc.

Next add QA as approver for a merge to master, thus make it mandatory that QA signs of a merge request to master and integrate quality in the development cycle or have a master that is always ready for release.

One could opt to work from master and for a release tag the master branch with a version tag, as per above example.

OR 

like gitlab does it, to create a branch for each release, cherry pick the features from master that are ready or planned and then tag the branch with a version tag.

where as a version tag creates a deployment for a commit, release or a RC.