Skip to content

Instantly share code, notes, and snippets.

@mjeffryes
Created August 15, 2025 18:12
Show Gist options
  • Select an option

  • Save mjeffryes/ec181f0e0593d9735fdeb6b4f9d0cb84 to your computer and use it in GitHub Desktop.

Select an option

Save mjeffryes/ec181f0e0593d9735fdeb6b4f9d0cb84 to your computer and use it in GitHub Desktop.
Script to checkout a GitHub PR branch from a fork and push it to a new branch in target repo. This is useful for testing PRs from forks in the main repository.
#!/bin/bash
# Script to checkout a GitHub PR branch from a fork and push it to a new branch in target repo
# This is useful for testing PRs from forks in the main repository.
set -euo pipefail
# Check if PR URL is provided
if [ $# -eq 0 ]; then
echo "Usage: $0 <github-pr-url>"
echo "Example: $0 https://github.com/owner/repo/pull/123"
exit 1
fi
PR_URL="$1"
# Extract owner, repo, and PR number from URL
if [[ ! "$PR_URL" =~ github\.com/([^/]+)/([^/]+)/pull/([0-9]+) ]]; then
echo "Error: Invalid GitHub PR URL format"
echo "Expected format: https://github.com/owner/repo/pull/NUMBER"
exit 1
fi
OWNER="${BASH_REMATCH[1]}"
REPO="${BASH_REMATCH[2]}"
PR_NUMBER="${BASH_REMATCH[3]}"
echo "Fetching PR information for $OWNER/$REPO#$PR_NUMBER..."
# Get PR information using gh CLI
PR_INFO=$(gh pr view "$PR_NUMBER" --repo "$OWNER/$REPO" --json headRefName,headRepository,headRepositoryOwner,baseRefName,isCrossRepository)
# Extract branch name and repository information
HEAD_BRANCH=$(echo "$PR_INFO" | jq -r '.headRefName')
HEAD_REPO_NAME=$(echo "$PR_INFO" | jq -r '.headRepository.name')
HEAD_REPO_OWNER=$(echo "$PR_INFO" | jq -r '.headRepositoryOwner.login')
IS_CROSS_REPO=$(echo "$PR_INFO" | jq -r '.isCrossRepository')
BASE_REPO="$OWNER/$REPO" # The base repo is the one we're querying
# Construct head repository name
if [ "$IS_CROSS_REPO" = "true" ]; then
HEAD_REPO="$HEAD_REPO_OWNER/$HEAD_REPO_NAME"
else
HEAD_REPO="$BASE_REPO"
fi
echo "Source branch: $HEAD_BRANCH"
echo "Source repo: $HEAD_REPO"
echo "Target repo: $BASE_REPO"
NEW_BRANCH_NAME="pr-$PR_NUMBER-$HEAD_BRANCH"
echo "New branch name: $NEW_BRANCH_NAME"
# Check if we need to clone the target repository
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
# Create temp directory and clone target repository
TEMP_DIR=$(mktemp -d)
echo "Creating temporary directory: $TEMP_DIR"
cd "$TEMP_DIR"
echo "Cloning target repository..."
git clone "https://github.com/$OWNER/$REPO.git"
cd "$REPO"
# Set cleanup trap
trap "rm -rf '$TEMP_DIR'" EXIT
fi
# Add the source repository as a remote if it's different from the base repo
if [ "$HEAD_REPO" != "$BASE_REPO" ]; then
REMOTE_NAME="pr-source-$PR_NUMBER"
echo "Adding remote for source repository..."
echo "DEBUG: Adding remote $REMOTE_NAME with URL https://github.com/$HEAD_REPO.git"
# Remove existing remote if it exists
git remote remove "$REMOTE_NAME" 2>/dev/null || true
git remote add "$REMOTE_NAME" "https://github.com/$HEAD_REPO.git"
git fetch "$REMOTE_NAME"
SOURCE_REF="$REMOTE_NAME/$HEAD_BRANCH"
else
git fetch origin
SOURCE_REF="origin/$HEAD_BRANCH"
fi
# Checkout the PR branch
echo "Checking out branch $HEAD_BRANCH..."
git checkout -b "$NEW_BRANCH_NAME" "$SOURCE_REF"
# Push the new branch to origin
echo "Pushing new branch $NEW_BRANCH_NAME to origin..."
git push -u origin "$NEW_BRANCH_NAME"
echo "Successfully created and pushed branch: $NEW_BRANCH_NAME"
echo "Branch is now available in the target repository"
# Clean up remote if we added one
if [ "$HEAD_REPO" != "$BASE_REPO" ]; then
git remote remove "$REMOTE_NAME"
echo "Cleaned up temporary remote: $REMOTE_NAME"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment