Skip to content

Instantly share code, notes, and snippets.

@eddiemoya
Last active August 5, 2022 15:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eddiemoya/0a58e3f8c23523fe10fcdcb2c7daefbc to your computer and use it in GitHub Desktop.
Save eddiemoya/0a58e3f8c23523fe10fcdcb2c7daefbc to your computer and use it in GitHub Desktop.
Checks to see if the given branch is fast-forward-mergable with the given base. If not, it attempts to rebase the branch. If any conflicts arise, the rebase is aborted and the script exists with non-zero status.
#!/bin/bash
underline=$(tput sgr 0 1) # Underline
bold=$(tput bold) # Bold
normal=$(tput rmso) # Normal
# Dims
red=$(tput setaf 1) # red
green=$(tput setaf 2) # magenta
blue=$(tput setaf 4) # blue
yellow=$(tput setaf 3) # yellow
magenta=$(tput setaf 5) # magenta
cyan=$(tput setaf 6) # cyan
white=$(tput setaf 7) # white
#Reset
reset=$(tput sgr0) # Reset
function get_merge_revs {
MERGE=$(git rev-parse --abbrev-ref $REV);
MERGE_REV=$(git rev-parse $REV);
SHORT_MERGE_REV=$(echo $MERGE_REV | cut -c 1-7);
}
function get_orig_merge_revs {
ORIG_MERGE=$(git rev-parse --abbrev-ref $REV);
ORIG_MERGE_REV=$(git rev-parse $REV);
ORIG_SHORT_MERGE_REV=$(echo $MERGE_REV | cut -c 1-7);
}
function get_base_revs {
CURRENT=$(git rev-parse --abbrev-ref $REV);
CURRENT_REV=$(git rev-parse $REV);
SHORT_CURRENT_REV=$(echo $CURRENT_REV | cut -c 1-7);
}
function is_ffable {
echo ".....";
git merge-base --is-ancestor $CURRENT_REV $MERGE_REV;
ffable=$?;
if [ $VERBOSE == true ]; then
echo -e "${cyan}(A)${reset}: (${cyan}$CURRENT${reset}) \t[${cyan}$CURRENT_REV${reset}]";
echo -e "${magenta}(B)${reset}: (${magenta}$MERGE${reset}) \t[${magenta}$MERGE_REV${reset}]\n";
if [ $ffable == 0 ]; then
echo -e "${green}[*] Yes! Revision ${B_label}${green} CAN be Fast-Forward merged into ${A_label}${green}.${reset}"
else
echo -e "${red}[!] Well, fuck! Revision ${B_label}${red} can NOT be Fast-Forward merged into ${A_label}${green}!${reset}"
fi
fi
}
# Performs a reverse rebase where the current revision becomes the base for the revision that is passed.
function mebase {
# echo "Checking out $MERGE.....";
git checkout --quiet $MERGE;
TMP_REV=$(git rev-parse HEAD);
# Verify that we have checked out the correct revision
if [ "$MERGE_REV" == "$TMP_REV" ]; then
echo "Performing rebase of ($MERGE) [$SHORT_MERGE_REV] onto ($CURRENT) [$SHORT_CURRENT_REV]...";
echo ".....";
git rebase --quiet $CURRENT_REV > /dev/null;
has_conflicts=$(git status --porcelain | grep "U");
# local merged_files=$(git status --porcelain);
if [ -n "$has_conflicts" ]; then
echo "${red}";
echo -e "[!] Conflicting files";
echo ${has_conflicts} | sed 's/UU/\'$'\nUU/g';
echo "${reset}";
echo -e "[*] Branch has conflicts. Aboting Rebase...";
git rebase --abort;
else
#Reset the merge vars
REV="HEAD";
echo "[*] Revision ($MERGE) [$SHORT_MERGE_REV] has been properly rebased onto ($CURRENT) [$SHORT_CURRENT_REV] and updated.";
get_merge_revs;
fi
# echo "[*] Checking out your original branch: ($CURRENT) [$SHORT_CURRENT_REV]...";
git checkout --quiet $ORIG_MERGE;
else
echo "\n${attention}[!] Checkout of $MERGE seems to have failed. Check spelling, make sure you pushed, try again."
exit() { return $1;}
fi
}
function ask_rebase {
printf "[${blue}?${reset}] Perform ${underline}${red}rebase${reset}? [Yes/no] : "
read do_rebase;
}
REV="HEAD";
get_orig_merge_revs;
REV=$1;
get_merge_revs;
REV=$2;
get_base_revs;
echo "Current position is [${cyan}$SHORT_CURRENT_REV${reset}] (${cyan}$CURRENT${reset})";
#Backup var for safe keeping after rebases.
BRANCH=$MERGE;
VERBOSE=true;
is_ffable;
if [ "$ffable" -gt 0 ]; then
ask_rebase;
if [ $do_rebase == "Yes" ]; then
mebase;
if [ -n "$has_conflicts" ]; then
exit() { return $1;}
else
echo -e "\nNew revisions (after rebase)"
is_ffable;
fi
else
echo "Nothing left to do...";
exit() { return $1;}
fi
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment