Skip to content

Instantly share code, notes, and snippets.

@BlueskyFR
Last active July 2, 2024 14:50
Show Gist options
  • Save BlueskyFR/9db8e139bfbf0e1012997631459b1568 to your computer and use it in GitHub Desktop.
Save BlueskyFR/9db8e139bfbf0e1012997631459b1568 to your computer and use it in GitHub Desktop.
Rebases a branch and manages history when the target branch rebases itself off another one
#!/usr/bin/env bash
# Fail on first non-zero exit code
set -e
setup_colors() {
if [[ -t 2 ]] && [[ -z "${NO_COLOR-}" ]] && [[ "${TERM-}" != "dumb" ]]; then
NOFORMAT='\033[0m' RED='\033[0;31m' GREEN='\033[0;32m' ORANGE='\033[0;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' YELLOW='\033[1;33m'
else
NOFORMAT='' RED='' GREEN='' ORANGE='' BLUE='' PURPLE='' CYAN='' YELLOW=''
fi
}
msg() {
PREFIX=
[[ "$1" == "-n" ]] && { PREFIX=$1; shift; }
echo >&2 -e $PREFIX "${1-}"
}
setup_colors
# This will also issue a warning if we are not currently in a git repository
git_dir=$(git rev-parse --absolute-git-dir)
# Get the first argument of the script
rebase_branch="$1"
# Display a warning if the argument wasn't provided
if [[ -z "$rebase_branch" ]]; then
msg "${RED}⚠️ Please provide a branch name to rebase onto${NOFORMAT}"
exit 1
fi
# Exit if $rebase_branch contains whitespaces
if [[ "$rebase_branch" =~ \ ]]; then
msg "${RED}Are you sure you want whitespaces in the branch name? 🧐${NOFORMAT}"
exit 1
fi
current_branch=$(git branch --show-current)
# Filename matching the current branch with the one provided
file=$git_dir/rebase-$current_branch-on-$rebase_branch
prompt_last_commit_hash() {
msg "${BLUE}What is the last commit hash of ${YELLOW}$rebase_branch${BLUE} you have on your branch (${YELLOW}$current_branch${BLUE})?${NOFORMAT}"
read -r -p ">> " last_hash
msg "${BLUE}Saving hash in $file...${NOFORMAT}"
echo $last_hash > $file
}
# Record the last hash the branch was rebased on if we did not save it last time
if [[ ! -f "$file" ]]; then
prompt_last_commit_hash
else
last_hash=$(cat $file)
msg "${BLUE}Hello back! It seems your branch was last rebased on this commit:${NOFORMAT}"
git --no-pager log -1 --oneline $last_hash
read -r -p "Can you confirm? [Y/N] " answer
if [[ "$answer" =~ ^([yY][eE][sS]|[yY])$ ]]; then
msg "${BLUE}Great! ✨${NOFORMAT}"
elif [[ "$answer" =~ ^([nN][oO]|[nN])$ ]]; then
prompt_last_commit_hash
else
msg "${RED}Invalid answer!${NOFORMAT}"
exit 1
fi
fi
msg "${PURPLE}[1/3] Fetching remote changes...${NOFORMAT}"
git fetch -p
# Do the actual rebase
msg "${PURPLE}[2/3] Rebasing ${YELLOW}$current_branch${PURPLE} onto ${YELLOW}origin/$rebase_branch${PURPLE} based on commit ${YELLOW}$last_hash${PURPLE}...${NOFORMAT}"
git rebase --onto origin/$rebase_branch $last_hash
# Remember what is the last commit of origin/$rebase_branch for next time
msg "${BLUE}[3/3] Saving the last commit hash of origin/$rebase_branch for next time...${NOFORMAT}"
msg "${BLUE} (in $file)${NOFORMAT}"
origin_last_hash=$(git rev-parse origin/$rebase_branch)
echo $origin_last_hash > $file
msg "${GREEN}Rebase successful! 🎉${NOFORMAT}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment