When trying to merge-patch it will fail if the branch you are trying to merge is already on the local machine. This will ask if you want to remove it. The branch will be removed locally and then pulled from the remote to ensure you are not merging any un-pushed local changes.
130 lines
3.2 KiB
Bash
Executable file
130 lines
3.2 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# Merges a remote branch into your current branch forcing a fast
|
|
# forward merge by rebasing first. This uses the rebase style of
|
|
# `--continue` and `--abort` when you have started to pick up where
|
|
# you left off
|
|
#
|
|
# Author: Ade Attwood <code@adeattwood.co.uk>
|
|
# Created: 2021-05-16
|
|
#
|
|
|
|
set -e
|
|
|
|
MERGE_BRANCH="$1";
|
|
|
|
#
|
|
# The merge branch argument is required
|
|
#
|
|
if [[ -z "$1" ]]; then
|
|
cat << HELP
|
|
Git Merge Patch
|
|
|
|
git merge-patch my-remote-branch
|
|
|
|
HELP
|
|
exit 1;
|
|
fi
|
|
|
|
#
|
|
# Test for merge conflicts can abort if any are found. Theses need to be
|
|
# resolved before you can continue
|
|
#
|
|
if [[ ! -z "$(git diff --name-only --diff-filter=U)" ]]; then
|
|
echo "ERROR: Conflicts found, you need to resolve them before you continue your"
|
|
echo "merge-patch. Use 'git am --show-current-patch' to see the failed patch. Then you"
|
|
echo "can continue the merge-patch with 'git merge-patch --continue'"
|
|
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "$MERGE_BRANCH" == "--abort" ]] || [[ "$MERGE_BRANCH" == "--skip" ]]; then
|
|
#
|
|
# If we are in a rebase state then we want to abort that to
|
|
#
|
|
if [[ -f "$(git rev-parse --show-toplevel)/.git/REBASE_HEAD" ]]; then
|
|
git rebase $MERGE_BRANCH
|
|
fi
|
|
|
|
if [[ -f "$(git rev-parse --show-toplevel)/.git/MERGE_PATCH" ]]; then
|
|
rm "$(git rev-parse --show-toplevel)/.git/MERGE_PATCH"
|
|
fi
|
|
|
|
exit 0
|
|
fi
|
|
|
|
if [[ "$MERGE_BRANCH" != "--continue" ]]; then
|
|
branch=$(git rev-parse --abbrev-ref HEAD);
|
|
echo "$branch" > "$(git rev-parse --show-toplevel)/.git/MERGE_PATCH"
|
|
|
|
#
|
|
# Fetch from remove so every ting is upto date
|
|
#
|
|
git fetch
|
|
|
|
#
|
|
# Ask the user if they would like to remove the local branch if it exists locally
|
|
#
|
|
if [[ ! -z "$(git branch --list $MERGE_BRANCH)" ]]; then
|
|
while true; do
|
|
read -p "Branch '$MERGE_BRANCH' exists locally would you like to remove it? " yn
|
|
case $yn in
|
|
[Yy]* ) git branch -D "$MERGE_BRANCH"; break;;
|
|
[Nn]* ) echo "Exiting you need to remove branch '$MERGE_BRANCH' manually before merge-patching"; exit;;
|
|
* ) echo "Please answer yes or no.";;
|
|
esac
|
|
done
|
|
fi
|
|
|
|
#
|
|
# Check out the merge branch from the origin
|
|
#
|
|
git checkout -b "$MERGE_BRANCH" "origin/$MERGE_BRANCH"
|
|
|
|
#
|
|
# Ensure the target branch is up to date
|
|
#
|
|
git checkout $branch
|
|
git pull origin $branch
|
|
git checkout $MERGE_BRANCH
|
|
|
|
#
|
|
# Rebase onto branch so we don't create a merge commit
|
|
#
|
|
git rebase $branch;
|
|
else
|
|
if [[ ! -f "$(git rev-parse --show-toplevel)/.git/MERGE_PATCH" ]]; then
|
|
echo "ERROR: Merge patch has not been started"
|
|
exit 1;
|
|
fi
|
|
|
|
#
|
|
# If we are still in the rebase from above then we need to
|
|
# continue with that before we finish merging the patch
|
|
#
|
|
if [[ -f "$(git rev-parse --show-toplevel)/.git/REBASE_HEAD" ]]; then
|
|
git rebase --continue
|
|
fi
|
|
|
|
MERGE_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
|
branch="$(cat $(git rev-parse --show-toplevel)/.git/MERGE_PATCH)"
|
|
fi
|
|
|
|
#
|
|
# Force push the rebased branch to the remove so Gitlab
|
|
# recognises the hash has been merged
|
|
#
|
|
git push origin "$MERGE_BRANCH" -f -o ci.skip
|
|
|
|
#
|
|
# Merge into the target branch ensuring its a fast forward merge
|
|
#
|
|
git checkout $branch
|
|
git merge --ff-only --log $MERGE_BRANCH;
|
|
|
|
#
|
|
# Clean up the MERGE_PATCH file now we have completed the merge
|
|
#
|
|
if [[ -f "$(git rev-parse --show-toplevel)/.git/MERGE_PATCH" ]]; then
|
|
rm "$(git rev-parse --show-toplevel)/.git/MERGE_PATCH"
|
|
fi
|