Context : My team is following a standard Git flow, with branches release and develop and we have recurring conflicts problems when merging release into develop. I suspect a problem coming from the merge strategy.
Here is a scenario :
The initial situation is a file named hello.txt containing only 1,2,3. The sequence is :
- Create a PR from
releasein order to add a line4, 5, 6and merge it - Create a PR from
developto report this commit and merge it - Create a PR from
developin order to add a line7, 8, 9and merge it - Create a PR from
developin order to mergereleaseintodevelop
Depending on the merge strategy, there is a conflict. To my understanding, Git should "see" (but I don't understand how it works) that the "4, 5, 6" commit from release has already been reported to develop. Somehow, it seems that it is not always the case when merging PRs with git merge --squash.
Here are the results I get :
- With a simple
git mergestrategy, everything is fine - With
git merge --squash && git commit --no-edit, there are no conflicts but the commit messages are messy in the logs - With
git merge --squash && git commit -m "Report --- into ---", there is a conflict
Questions : Am I doing something wrong with the way I report commits (see below) ? Or is merge --squash not recommended when using Git flow ? Also, how does git identifies commits to be merged ? Why just changing the commit messages affects it ?
Here is a shell script which creates a temporary git repo and does the previously mentioned git operations. It is intended to mimic PR creation/merge as performed by BitBucket with the merge strategy used in my team. Please take a look at the function called merge as it allows to change the merge strategy.
CAUTION : never execute a shell script if you do not fully understand what it does.
#! /bin/bash
set -euo pipefail
IFS=$'\n\t'
function log_step() {
echo -e "\n\e[96m${*}\e[0m"
}
# Delegates the call to the merge strategy and passing args
# You can uncomment the desired strategy
function merge()
{
# merge_simple $*
merge_squash_rename $*
# merge_squash_no_edit $*
}
function merge_squash_rename(){
echo -e "\e[94mMerge ${1} into ${2}\e[0m"
git checkout ${2}
git merge --squash ${1}
git commit -m "Merge ${1} into ${2}"
}
function merge_squash_no_edit(){
echo -e "\e[94mMerge ${1} into ${2}\e[0m"
git checkout ${2}
git merge --squash ${1}
git commit --no-edit
}
function merge_simple(){
echo -e "\e[94mMerge ${1} into ${2}\e[0m"
git checkout ${2}
git merge ${1}
}
tmp_dir=$(mktemp -d -t strategit-XXXXXXXX)
echo "Created directory ${tmp_dir}"
cd ${tmp_dir}
# Initial state : a file named hello.txt, containing "1,2,3"
log_step "Create initial file with 1,2,3"
git init
echo '1,2,3' >> hello.txt
git add hello.txt
git commit -m 'First commit'
# Create initial branches release + develop
log_step "Create branches release and develop"
git checkout -b release
git checkout -b develop
# Work on ticket FW-456 on release
log_step "Create PR on release in order to add the line 4,5,6"
git checkout release
git checkout -b feature/FW-456
echo '4,5,6' >> hello.txt
git add hello.txt
git commit -m 'feature/FW-456'
# Keep it for cherry-pick later
ORIGINAL_COMMIT_HASH=$(git rev-parse HEAD)
log_step "Merge the PR on release"
merge feature/FW-456 release
# report PR on develop by creating a report branch
log_step "Create the report branch from develop"
git checkout develop
git checkout -b report/feature/FW-456
git cherry-pick ${ORIGINAL_COMMIT_HASH}
log_step "Merge the report branch on develop"
merge report/feature/FW-456 develop
# Work on ticket FW-789 on develop
log_step "Create a new PR from develop to add the line 7,8,9"
git checkout develop
git checkout -b feature/FW-789
echo '7,8,9' >> hello.txt
git add hello.txt
git commit -m 'feature/FW-789'
log_step "Merge the PR in develop"
merge feature/FW-789 develop
# Now, report release into develop
log_step "Create a PR on develop to report release in develop"
git checkout develop
git checkout -b chore/report-release-into-develop
# "|| true" to prevent script from exiting because of the potential conflict error
log_step "Try to merge"
git merge release || true
echo ""
echo "***************************************************"
echo "* *"
echo -e "* See result in directory \e[92m${tmp_dir}\e[0m *"
echo "* *"
echo "***************************************************"