Skip to content

Instantly share code, notes, and snippets.

@Mohan-Zhang-u
Last active July 22, 2024 06:08
Show Gist options
  • Save Mohan-Zhang-u/f2c34b60ed4c60e6d88cf9032e5e0207 to your computer and use it in GitHub Desktop.
Save Mohan-Zhang-u/f2c34b60ed4c60e6d88cf9032e5e0207 to your computer and use it in GitHub Desktop.
#!/bin/bash
set -e
# Usage:
# ./privatefork.sh <public-repository-url> [-p <personal-access-token>] [-n]
### Environment Variables
# - Public repository URL
# -p: `PAT` (Personal Access Token), optionally provided and will override the default PAT.
# -n: Skip cleanup of the local repository clone.
### NOTE: You could set up the script as an executable and making it globally available:
# sudo chmod +x privatefork.sh
# sudo cp privatefork.sh /usr/local/bin
# echo 'export PATH="$PATH:/usr/local/bin"' >> ~/.bashrc
### Script Functions:
# 1. Clone the specified GitHub repository.
# 2. Create a private fork of the repository on the user's GitHub account.
# 3. Push all branches from the cloned repository to the new private fork.
### Packages Required
# - Shell Script
# - Git
# - GitHub API
# - python
PAT=ghp_XXXXX # Default PAT, replace or use -p flag to overwrite
skip_cleanup=false # Variable to control cleanup
# Function to display usage
usage() {
echo "Usage: $0 <repository-url> [-p <personal-access-token>] [-n]"
echo " -p: Specify a personal access token"
echo " -n: Skip cleanup of the local repository clone"
exit 1
}
#### Packages Required
# - Shell Script
# - Git
# - GitHub API
# - python, or jq (Command-line JSON processor)
# Check if at least one argument is provided
if [ "$#" -eq 0 ]; then
usage
fi
# Mandatory argument
REPO_URL="$1"
shift
# Parse optional arguments
while getopts ":p:n" opt; do
case $opt in
p)
PAT=$OPTARG
;;
n)
skip_cleanup=true
;;
\?)
echo "Invalid option: -$OPTARG" >&2
usage
;;
:)
echo "Option -$OPTARG requires an argument." >&2
usage
;;
esac
done
echo "Personal Access Token: $PAT"
echo "skip cleanup $skip_cleanup"
REPO_NAME=$(basename -s .git "$REPO_URL")
# Use Python to parse JSON and extract the user's login name
USER_NAME=$(curl -s -H "Authorization: token $PAT" https://api.github.com/user | python -c "import sys, json; print(json.load(sys.stdin)['login'])")
# or, use jq to parse JSON and extract the user's login name
# USER_NAME=$(curl -s -H "Authorization: token $PAT" https://api.github.com/user | jq -r .login)
NEW_REPO_URL="https://$USER_NAME:$PAT@github.com/$USER_NAME/$REPO_NAME.git"
# Clone the repository
git clone --mirror "$REPO_URL"
cd "$REPO_NAME.git" || exit
# Set the original repository as the upstream for fetching updates
git remote add upstream "$REPO_URL"
# Disable push to upstream
git remote set-url --push upstream DISABLE
# Create a new private repository on GitHub
curl -H "Authorization: token $PAT" https://api.github.com/user/repos -d "{\"name\":\"$REPO_NAME\",\"private\":true}"
# # Push all branches to the new private repository
# git push --mirror "$NEW_REPO_URL"
# List all local branches and filter out pull request refs
branches=$(git for-each-ref --format='%(refname)' refs/heads/)
# Push each branch individually to avoid pushing pull request refs
for branch in $branches; do
git push "$NEW_REPO_URL" "${branch}:refs/heads/$(basename $branch)"
done
# Cleanup
if [ "$skip_cleanup" = false ]; then
echo "Cleaning up..."
cd ..
rm -rf "$REPO_NAME.git"
fi
echo "Private fork created and all branches pushed to $NEW_REPO_URL"
@Mohan-Zhang-u
Copy link
Author

Here is the script for you to fork a repo and make it private. This script maintains the old public repo as "upstream", and your private repo as "origin"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment