Skip to content

Instantly share code, notes, and snippets.

@R0rt1z2
Created March 24, 2025 18:13
Show Gist options
  • Save R0rt1z2/e88e2d220f71332c21b424aa45e8b16e to your computer and use it in GitHub Desktop.
Save R0rt1z2/e88e2d220f71332c21b424aa45e8b16e to your computer and use it in GitHub Desktop.
#!/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