-
-
Save hyperupcall/7edd9f31843d40b12c1db2ff40a283d9 to your computer and use it in GitHub Desktop.
| #!/bin/sh -eu | |
| # code licensed under BSD 2-Clause "Simplified" License | |
| # see `change-master-branch-to-main.sh --help` for usage | |
| # see twitter thread for more details: https://twitter.com/EdwinKofler/status/1272729160620752898 | |
| site="github.com" | |
| oldDefaultBranch="master" | |
| newDefaultBranch="main" | |
| bin="gh" # or set to 'hub' | |
| user="${1:-""}" | |
| repo="${2:-""}" | |
| # ------------------- helper functions ------------------- # | |
| showHelp() { | |
| echo "change-master-branch-to-main.sh" | |
| echo | |
| echo "Description:" | |
| echo " Cross-platform shell script to change the 'master' branch to" | |
| echo " 'main' for the local and remote repository. Should work with" | |
| echo " providers besides Github, but I haven't tested that" | |
| echo | |
| echo "Usage:" | |
| echo " change-master-branch-to-main.sh [username] [repo name]" | |
| echo " Rename the 'master' branch to 'main' both for the local" | |
| echo " and remote repository with the specified variables. It" | |
| echo " also sets the default branch to 'main' if the previous" | |
| echo " default was 'master'" | |
| echo " change-master-branch-to-main.sh" | |
| echo " Same as above, but intelligently guesses (and ask user for" | |
| echo " confirmation) the github user and repo names" | |
| echo | |
| echo "Requirements:" | |
| echo " 'jq' and 'gh' are optional dependencies and are only required" | |
| echo " when trying to update the GitHub default branch" | |
| echo | |
| echo "Examples:" | |
| echo " change-master-branch-to-main.sh eankeen deno-babel" | |
| } | |
| # get the GitHub username, if it wasn't already specified | |
| askUser() { | |
| # return if user is already set (passed as arg) | |
| test ! -z "$user" && return | |
| # get github username and strip quotes | |
| url="$(git config --get remote.origin.url)" | |
| # if url looks like [email protected]:user/repo | |
| if [ "$(echo "$url" | cut -d'@' -f1)" = "git" ]; then | |
| user="$(echo "$url" | sed -E "s/(.*:)(.*)(\/.*)/\2/g")" | |
| else | |
| user="$(echo "$url" | sed -E "s/(.*$site\/)(.*)(\/.*)/\2/g")" | |
| fi | |
| printInfo "github username (default: %s): " "$user" | |
| read -r | |
| # trim whitespace | |
| REPLY="$(echo "$REPLY" | xargs)" | |
| user="${REPLY:-$user}" | |
| printInfo "input: $user\n\n" | |
| } | |
| # get the GitHub repository name, if it wasn't already specified | |
| askRepo() { | |
| # return if repo is already set (passed as arg) | |
| test ! -z "$repo" && return | |
| url="$(git config --get remote.origin.url)" | |
| repo="$(basename -s .git "$url")" | |
| printInfo "github repository name (default: %s): " "$repo" | |
| read -r | |
| # trim whitespace | |
| REPLY="$(echo "$REPLY" | xargs)" | |
| repo="${REPLY:-$repo}" | |
| printInfo "input: $repo\n\n" | |
| } | |
| remoteMainExists() { | |
| git show-branch "refs/remotes/origin/$newDefaultBranch" >/dev/null 2>&1 | |
| } | |
| remoteMasterExists() { | |
| git show-branch "refs/remotes/origin/$oldDefaultBranch" >/dev/null 2>&1 | |
| } | |
| localMainExists() { | |
| git rev-parse --verify --quiet "refs/heads/$newDefaultBranch" >/dev/null | |
| } | |
| localMasterExists() { | |
| git rev-parse --verify --quiet "refs/heads/$oldDefaultBranch" >/dev/null | |
| } | |
| hasColor() { | |
| test -t 1 && command -v tput >/dev/null && \ | |
| test -n "$(tput colors)" && test "$(tput colors)" -ge 8 | |
| } | |
| hasBinAndJq() { | |
| command -v jq >/dev/null && command -v "$bin" >/dev/null | |
| } | |
| printInfo() { | |
| if hasColor; then | |
| printf "\033[0;94m" | |
| # shellcheck disable=SC2059 | |
| printf "$@" | |
| printf "\033[0m" | |
| else | |
| # shellcheck disable=SC2059 | |
| printf "$@" | |
| fi | |
| } | |
| # ------------------------- main ------------------------- # | |
| test "${1:-""}" = "--help" && showHelp && exit | |
| git fetch --all | |
| git checkout "$oldDefaultBranch" | |
| git push origin "$oldDefaultBranch" | |
| # ensure 'main' is the default locally | |
| if ! localMainExists; then | |
| printInfo "renaming '$oldDefaultBranch' to '$newDefaultBranch' locally\n" | |
| git checkout $oldDefaultBranch | |
| git branch --move $oldDefaultBranch "$newDefaultBranch" | |
| fi | |
| # ensure 'main' is at remote | |
| if ! remoteMainExists; then | |
| printInfo "setting '$newDefaultBranch' as default upstream branch\n" | |
| git checkout "$newDefaultBranch" | |
| git push --set-upstream origin "$newDefaultBranch" | |
| fi | |
| # remove local 'master' branch | |
| if localMasterExists; then | |
| printInfo "renaming local $oldDefaultBranch branch\n" | |
| git branch --delete $oldDefaultBranch | |
| fi | |
| # ensure github default branch is 'main' | |
| if hasBinAndJq; then | |
| askRepo | |
| askUser | |
| beforeNewbranch="$("$bin" api "repos/$user/$repo" -X GET | jq --raw-output ".default_branch")" | |
| # sets new default branch | |
| if test "$beforeNewbranch" = "$oldDefaultBranch"; then | |
| "$bin" api "repos/$user/$repo" -X PATCH -F default_branch="$newDefaultBranch" | |
| fi | |
| afterNewbranch="$("$bin" api "repos/$user/$repo" -X GET | jq --raw-output ".default_branch")" | |
| printInfo "default branch at $user/$repo was: '$beforeNewbranch'\n" | |
| printInfo "default branch at $user/$repo is now: '$afterNewbranch'\n" | |
| fi | |
| # remove remote 'master' branch | |
| if remoteMasterExists; then | |
| printInfo "deleting remote $oldDefaultBranch branch\n" | |
| # if this fails, it may be due to forgetting | |
| # to reset the default branch to 'main' on github | |
| git push origin --delete $oldDefaultBranch | |
| test ! $? && printInfo "this probably errored since '$oldDefaultBranch' is still the 'default branch' on github" \ | |
| && printInfo "if you install \`gh\` and \`jq\` this will be done for you" | |
| fi |
@hkatzdev yah! since your comment i added a variable at the top for that ;)
I don't know why but I kept getting ! [remote rejected] master (refusing to delete the current branch: refs/heads/master) error: failed to push some refs to 'https://github.com/hkatzdev/hackagotchi.git' when running the script. Every time I tried to clone with hub it wouldn't change the head ref, even though I ended up manually doing it in github. Maybe its a hub problem?
@hkatzdev can you please provide more output? like it should say default branch at hkatzdev/hackagotchi is now 'main' somewhere
i would recommend troubleshooting with hub api "repos/hkatzdev/hackagotchi" -X GET | jq and hub api "repos/hkatzdev/hackagotchi" -X PATCH -F default_branch="main". does that latter output anything? if not maybe there are some issues with authentication? you can also remove the >/dev/null from line 162 for more details
@eankeen it so cool. will this same script work for GITLAB as well ?
@eankeen it so cool. will this same script work for GITLAB as well ?
Thank you! It should work, provided you set I don't think GitLab is fully supported. To get complete support, you'll have to modify the requests starting near line 150 that use the site=gitlab.com near the top - but it's not tested :)gh or hub utility (basically anything that executes the utility referred to by "$bin")
This is really cool - would it be possible to add an option to change main to any name, in case people want trunk for instance?