Created
March 24, 2025 18:13
-
-
Save R0rt1z2/e88e2d220f71332c21b424aa45e8b16e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
REPO_PATH="" | |
REMOTE_URL="" | |
SOURCE_BRANCH="" | |
TARGET_BRANCH="" | |
TEMP_BRANCH="temp" | |
CHUNK_SIZE=8000 # Number of commits per chunk | |
GREEN='\033[0;32m' | |
YELLOW='\033[1;33m' | |
RED='\033[0;31m' | |
NC='\033[0m' | |
print_status() { | |
echo -e "${GREEN}[*] $1${NC}" | |
} | |
print_warning() { | |
echo -e "${YELLOW}[!] $1${NC}" | |
} | |
print_error() { | |
echo -e "${RED}[✗] $1${NC}" | |
} | |
cd "$REPO_PATH" || { print_error "Failed to change directory to $REPO_PATH"; exit 1; } | |
print_status "Working in repository: $(pwd)" | |
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) | |
if [ "$CURRENT_BRANCH" != "$SOURCE_BRANCH" ]; then | |
print_warning "Current branch is $CURRENT_BRANCH, not $SOURCE_BRANCH" | |
read -p "Switch to $SOURCE_BRANCH? (y/n) " -n 1 -r | |
echo | |
if [[ $REPLY =~ ^[Yy]$ ]]; then | |
git checkout "$SOURCE_BRANCH" || { print_error "Failed to checkout $SOURCE_BRANCH"; exit 1; } | |
else | |
print_error "Aborting as we're not on the correct branch" | |
exit 1 | |
fi | |
fi | |
print_status "Creating temporary branch: $TEMP_BRANCH" | |
git branch -D "$TEMP_BRANCH" 2>/dev/null # Delete if exists | |
git checkout -b "$TEMP_BRANCH" || { print_error "Failed to create temporary branch"; exit 1; } | |
TOTAL_COMMITS=$(git rev-list --count HEAD) | |
print_status "Total commits in repository: $TOTAL_COMMITS" | |
print_status "Getting list of commits..." | |
COMMIT_LIST=$(git rev-list --reverse HEAD) | |
COMMIT_ARRAY=($COMMIT_LIST) | |
NUM_CHUNKS=$(( (TOTAL_COMMITS + CHUNK_SIZE - 1) / CHUNK_SIZE )) | |
print_status "Will push in approximately $NUM_CHUNKS chunks of up to $CHUNK_SIZE commits each" | |
read -p "Ready to begin chunked push? (y/n) " -n 1 -r | |
echo | |
if [[ ! $REPLY =~ ^[Yy]$ ]]; then | |
print_error "Aborting chunked push" | |
git checkout "$SOURCE_BRANCH" | |
git branch -D "$TEMP_BRANCH" | |
exit 1 | |
fi | |
push_chunk_with_retry() { | |
local chunk_commit=$1 | |
local chunk_num=$2 | |
local start_idx=$3 | |
local end_idx=$4 | |
git reset --hard "$chunk_commit" || { print_error "Failed to reset to commit $chunk_commit"; return 1; } | |
while true; do | |
print_status "Pushing chunk $chunk_num/$NUM_CHUNKS to remote..." | |
if git push -f "$REMOTE_URL" "$TEMP_BRANCH:$TARGET_BRANCH"; then | |
print_status "Successfully pushed chunk $chunk_num/$NUM_CHUNKS" | |
return 0 | |
else | |
print_error "Failed to push chunk $chunk_num/$NUM_CHUNKS" | |
print_warning "Connection issue or remote error occurred" | |
print_warning "Current position: commits $start_idx to $end_idx of $TOTAL_COMMITS" | |
read -p "Retry this chunk? (y/n) " -n 1 -r | |
echo | |
if [[ ! $REPLY =~ ^[Yy]$ ]]; then | |
print_error "Aborting chunk push at user request" | |
return 1 | |
fi | |
print_status "Retrying chunk $chunk_num/$NUM_CHUNKS..." | |
sleep 2 | |
fi | |
done | |
} | |
CURRENT_CHUNK=1 | |
i=0 | |
while [ $i -lt $TOTAL_COMMITS ]; do | |
END_IDX=$((i + CHUNK_SIZE - 1)) | |
if [ $END_IDX -ge $TOTAL_COMMITS ]; then | |
END_IDX=$((TOTAL_COMMITS - 1)) | |
fi | |
CHUNK_COMMIT="${COMMIT_ARRAY[$END_IDX]}" | |
print_status "Processing chunk $CURRENT_CHUNK/$NUM_CHUNKS (commits $i to $END_IDX)" | |
if push_chunk_with_retry "$CHUNK_COMMIT" "$CURRENT_CHUNK" "$i" "$END_IDX"; then | |
i=$((i + CHUNK_SIZE)) | |
CURRENT_CHUNK=$((CURRENT_CHUNK + 1)) | |
else | |
print_warning "Failed to push chunk $CURRENT_CHUNK after retries" | |
read -p "Try with half the chunk size? (y/n) " -n 1 -r | |
echo | |
if [[ $REPLY =~ ^[Yy]$ ]]; then | |
CHUNK_SIZE=$((CHUNK_SIZE / 2)) | |
print_status "Adjusted chunk size to $CHUNK_SIZE" | |
NUM_CHUNKS=$(( (TOTAL_COMMITS - i + CHUNK_SIZE - 1) / CHUNK_SIZE + CURRENT_CHUNK - 1 )) | |
print_status "Will now push in approximately $NUM_CHUNKS total chunks" | |
else | |
print_error "Aborting chunked push at chunk $CURRENT_CHUNK" | |
break | |
fi | |
fi | |
done | |
print_status "Returning to original branch: $SOURCE_BRANCH" | |
git checkout "$SOURCE_BRANCH" || { print_warning "Failed to checkout original branch"; } | |
git branch -D "$TEMP_BRANCH" || { print_warning "Failed to delete temporary branch"; } | |
if [ $i -ge $TOTAL_COMMITS ]; then | |
print_status "Successfully pushed all chunks to $REMOTE_URL:$TARGET_BRANCH" | |
else | |
print_warning "Push operation did not complete all chunks" | |
print_warning "Pushed approximately $((i / CHUNK_SIZE)) chunks out of $NUM_CHUNKS" | |
print_warning "Last successful commit was around commit $i of $TOTAL_COMMITS" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment