I’ve been using Gitflow so many years.
I start from the develop branch. Create a feature branch and merge it back to develop when ready.
When all the features are ready and stable, I merge the develop branch to the release branch.
When the release branch is ready for production, I merge it to the hotfix branch to test the production rollout procedure.
And finally, when everything seems stable, I merge the hotfix branch to the main branch and tag it.

This is the theory.
What about the real experience?
What happens with a bug in production? Easy, I start from the main branch and merge my fix branch into the hotfix branch.
But I need this commit also to be available in the rest of the branches, release and develop.
What if I have a feature I must start two versions before? I can create a develop-2 branch. But I must ensure that this new branch is up-to-date with the new developments merged in the develop branch.
A lot of ifs.
So, I decided to create an auto-merge back.
First of all, this will only work in a Continuous Integration environment.
The auto-merge back will merge all the differences in the downside branches.
Here is the standard branch hierarchy: develop -> release -> hotfix -> main.
So, when merging something in main, the auto-merge back must automatically merge it to hotfix. This will trigger another job to merge it back to release. And so on.

Here it is:
#!/bin/bash
set -e
declare srcBranch destBranch
while [[ $# -gt 0 ]]; do
case $1 in
"--src-branch")
shift
srcBranch=$1
;;
"--dest-branch")
shift
destBranch=$1
;;
esac
shift
done
if [[ -z "$srcBranch" ]]; then
echo "The --src-branch argument is mandatory"
exit 1
elif [[ -z "$destBranch" ]]; then
echo "The --dest-branch argument is mandatory"
exit 1
fi
echo "CI_PROJECT_PATH: $CI_PROJECT_PATH"
echo "srcBranch: $srcBranch"
echo "destBranch: $destBranch"
git fetch
git checkout "$destBranch"
git pull
if [[ 0 = $(git diff origin/$srcBranch | wc -l ) ]] ; then exit 0 ; fi
git merge "origin/$srcBranch" --no-ff --no-edit
rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi
git push -u origin "$destBranch"
This script will merge the source branch to the destination branch. But it will first check if there is something to merge (to avoid unnecessary running jobs). Then, it tries to merge, but exit with a non-zero code if there is a conflict during the merge operation.
All this is done to be easily integration in a CI/CD pipelin.
When and where do I use this script?
As said, I put it in my Continuous Integration pipeline.
Where? At each new commit or merge in the protected branches. I use to create a dedicated job at GitlabCI such as this:
.auto-merge-template: &auto-merge-definition
stage: test
script:
- git clone ../gitlab-scritps
- chmod +x auto-merge.sh
- ./auto-merge.sh --src-branch $SRC_BRANCH --dest-branch $DST_BRANCH
auto-merge-develop:
<<: *auto-merge-definition
only:
- release
variables:
- SRC_BRANCH: release
- DST_BRANCH: develop
auto-merge-release:
<<: *auto-merge-definition
only:
- hotfix
variables:
- SRC_BRANCH: hotfix
- DST_BRANCH: release
auto-merge-hotfix:
<<: *auto-merge-definition
only:
- main
variables:
- SRC_BRANCH: main
- DST_BRANCH: hotfix
This way, all my branches are up-to-date with the upside changes.
And when adding a new branch for a new version or for new environments, I only need to update my downstream jobs.
I put this GitlabCI job in an early stage, to block the pipeline deployment if the merge fails. Otherwise, people tend to ignore it.
If you want to learn more about good quality code, make sure to follow me on Youtube.



Leave a comment