Skip to content

Instantly share code, notes, and snippets.

@brysonreece
Last active May 18, 2022 06:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brysonreece/219b994560155631856f5c127c8e0ba0 to your computer and use it in GitHub Desktop.
Save brysonreece/219b994560155631856f5c127c8e0ba0 to your computer and use it in GitHub Desktop.
Bitbucket to GitHub Migration Script
#! /bin/bash
# - Does not work with empty Bitbucket repositories
# - Does not work if repo description contains control characters, e.g. '\r'
ALL_REPOS=$@
# Check if any arguments were provided
if [[ $# -eq 0 ]]; then
echo "No repository name(s) provided!" 1>&2
exit 1
fi
# Define ANSI color codes
CLEAR='\033[0m'
RED='\033[00;31m'
GREEN='\033[00;32m'
YELLOW='\033[00;33m'
BLUE='\033[00;34m'
transfer_repo () {
REPO_NAME=$1
# Set up working directory...
WORK_DIR="/tmp/repo-migrations/${REPO_NAME}"
rm -rf $WORK_DIR
mkdir -p $WORK_DIR
# Get repo info from Bitbucket's API...
BB_REPO_JSON=$(curl --request GET -s \
--user $BITBUCKET_AUTH \
--url "https://api.bitbucket.org/2.0/repositories/$REPO_NAME" \
--header 'Accept: application/json')
# Parse out description and trunk name...
REPO_DESC=$(echo $BB_REPO_JSON | jq -r '.description' | tr -d '\r') || ''
TRUNK_NAME=$(echo $BB_REPO_JSON | jq -r '.mainbranch.name') || 'main'
# Clone the repo...
echo -e "[${BLUE}$REPO_NAME${CLEAR}] ${GREEN}Cloning: ${YELLOW}git@bitbucket.org:$REPO_NAME.git${GREEN} to ${YELLOW}$WORK_DIR${CLEAR}"
git clone --bare git@bitbucket.org:$REPO_NAME.git $WORK_DIR --quiet
cd $WORK_DIR
# Perform migration...
create_github_repo
rename_master_to_main
push_to_github
}
create_github_repo () {
if [ -n "$REPO_DESC" ]; then
echo -e "[${BLUE}$REPO_NAME${CLEAR}] ${YELLOW}Name:${CLEAR} $REPO_NAME"
echo -e "[${BLUE}$REPO_NAME${CLEAR}] ${YELLOW}Description:${CLEAR} $REPO_DESC"
echo -e -n "[${BLUE}$REPO_NAME${CLEAR}] ${GREEN}Creating GitHub repository... ${CLEAR}"
CREATE_OUTPUT=$(gh repo create $REPO_NAME --private --description="$REPO_DESC" 2>&1)
else
echo -e "[${BLUE}$REPO_NAME${CLEAR}] ${YELLOW}Name:${CLEAR} $REPO_NAME"
echo -e "[${BLUE}$REPO_NAME${CLEAR}] ${YELLOW}Description:${CLEAR} (none)"
echo -e -n "[${BLUE}$REPO_NAME${CLEAR}] ${GREEN}Creating GitHub repository... ${CLEAR}"
CREATE_OUTPUT=$(gh repo create $REPO_NAME --private 2>&1)
fi
if [ $? -eq 0 ]; then
echo -e "${GREEN}Done!${CLEAR}"
elif [[ $CREATE_OUTPUT == *"Name already exists"* ]]; then
echo -e "${YELLOW}Already exists!${CLEAR}" 1>&2
echo -e "[${BLUE}$REPO_NAME${CLEAR}] ${YELLOW}Could not create GitHub repository, it already exists.${CLEAR}" 1>&2
else
echo -e "${RED}Failed!${CLEAR}" 1>&2
echo -e "[${BLUE}$REPO_NAME${CLEAR}] ${RED}Could not create GitHub repository for some unknown reason.${CLEAR}" 1>&2
exit 1
fi
}
rename_master_to_main () {
# Rename trunk if needed
if [[ $TRUNK_NAME == "master" ]]; then
echo -e -n "[${BLUE}$REPO_NAME${CLEAR}] Renaming master to main... "
git branch -m master main --quiet
if [ $? -eq 0 ]; then
echo -e "${GREEN}Done!${CLEAR}"
else
echo -e "${RED}Failed!${CLEAR}" 1>&2
echo -e "[${BLUE}$REPO_NAME${CLEAR}] ${RED}Could not rename master branch to main automatically, please change manually using GitHub web UI.${CLEAR}" 1>&2
exit 1
fi
fi
}
push_to_github () {
# Push mirror to GitHub
echo -e -n "[${BLUE}$REPO_NAME${CLEAR}] Pushing to GitHub... "
git push --mirror https://github.com/$REPO_NAME.git --quiet
if [ $? -eq 0 ]; then
echo -e "${GREEN}Done!${CLEAR}"
else
echo -e "${RED}Failed!${CLEAR}"
echo -e "${RED}ERROR: Could not pushed changed repository to GitHub.${CLEAR}" 1>&2
exit 1
fi
}
for REPO in ${ALL_REPOS[@]}
do
transfer_repo $REPO
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment