Skip to content

Instantly share code, notes, and snippets.

@wch
Created September 25, 2025 13:38
Show Gist options
  • Select an option

  • Save wch/cc51dd0edf6b245c1680a3c211a14a6b to your computer and use it in GitHub Desktop.

Select an option

Save wch/cc51dd0edf6b245c1680a3c211a14a6b to your computer and use it in GitHub Desktop.
Rebase git branch, reformatting each changed file with prettier after each commit
#!/bin/bash
# Rebase with Prettier - Automatically reformat files with prettier during rebase
#
# USAGE:
# ./rebase-prettier-exec.sh
#
# BEFORE RUNNING:
# - Make sure you're on the branch you want to rebase (e.g., your feature branch)
# - This script will rebase your current branch onto origin/main
# - Ensure origin/main is up to date: git fetch origin
#
# DESCRIPTION:
# This script helps rebase your current branch onto origin/main while automatically
# converting space indentation to tab indentation using Prettier. It's designed
# to handle the common problem where your branch uses spaces but the main branch
# has switched to tabs.
#
# HOW IT WORKS:
# 1. Creates a backup branch for safety
# 2. Starts rebase with --ignore-space-change strategies to minimize conflicts
# 3. Runs Prettier after each commit using git's --exec flag
# 4. Only formats files that were changed in each original commit
# 5. Preserves commit messages and history
#
# REQUIREMENTS:
# - npm/npx and Prettier must be installed (run 'npm install' first)
# - Your project should have a .prettierrc config that specifies tabs
#
# CONFLICT RESOLUTION:
# If conflicts occur:
# 1. Fix the merge conflicts in your editor
# 2. Run: npx prettier --write <file> on each resolved file
# 3. Stage: git add <file>
# 4. Continue: git rebase --continue
#
# TO ABORT:
# git rebase --abort
# git checkout <backup-branch-name>
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}=== Rebase with Prettier (using --exec) ===${NC}"
echo ""
# Check if prettier is available
if ! command -v npx &> /dev/null || ! npx prettier --version &> /dev/null; then
echo -e "${RED}Error: Prettier is not available${NC}"
echo "Make sure you have run 'npm install' in this project"
exit 1
fi
# Check if we're in the middle of a rebase
if [ -d ".git/rebase-merge" ] || [ -d ".git/rebase-apply" ]; then
echo -e "${RED}Error: A rebase is already in progress!${NC}"
echo "Finish or abort the current rebase first with:"
echo " git rebase --continue OR git rebase --abort"
exit 1
fi
# Get current branch name
CURRENT_BRANCH=$(git branch --show-current)
if [ -z "$CURRENT_BRANCH" ]; then
echo -e "${RED}Error: Not on a branch${NC}"
exit 1
fi
# Create backup
BACKUP_BRANCH="${CURRENT_BRANCH}-backup-$(date +%Y%m%d-%H%M%S)"
echo -e "${YELLOW}Creating backup branch: ${BACKUP_BRANCH}${NC}"
git branch "$BACKUP_BRANCH"
# Create a prettier formatting script
PRETTIER_SCRIPT=$(mktemp /tmp/prettier-format-XXXXXX.sh)
cat > "$PRETTIER_SCRIPT" << 'EOF'
#!/bin/bash
# Format changed files with prettier
# Get list of files changed in the last commit
FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | grep -E '\.(ts|tsx|js|jsx)$' || true)
if [ -n "$FILES" ]; then
echo "Formatting files with Prettier..."
echo "$FILES" | while read -r file; do
if [ -f "$file" ]; then
echo " → $file"
npx prettier --write "$file" 2>/dev/null || true
# Only add this specific file that was part of the original commit
git add "$file" 2>/dev/null || true
fi
done
# Amend the commit if there are changes
if ! git diff --cached --quiet; then
git commit --amend --no-edit --no-verify
echo "✓ Formatting applied to commit"
fi
fi
EOF
chmod +x "$PRETTIER_SCRIPT"
echo -e "${GREEN}Starting rebase onto origin/main...${NC}"
echo "Configuration:"
echo " - Using ignore-space strategies to minimize conflicts"
echo " - Running Prettier after each commit"
echo " - Backup saved to: $BACKUP_BRANCH"
echo ""
# Perform the rebase with --exec to run prettier after each commit
if git rebase origin/main \
--strategy=recursive \
--strategy-option=ignore-space-change \
--strategy-option=ignore-all-space \
--exec "$PRETTIER_SCRIPT"; then
echo ""
echo -e "${GREEN}=== Rebase completed successfully! ===${NC}"
echo ""
# Run prettier on all files one final time
echo "Running final Prettier pass..."
git diff origin/main --name-only | grep -E '\.(ts|tsx|js|jsx|css)$' | while read -r file; do
if [ -f "$file" ]; then
npx prettier --write "$file" 2>/dev/null || true
git add "$file" 2>/dev/null || true
fi
done
# Amend if needed
if ! git diff --cached --quiet; then
git commit --amend --no-edit --no-verify
echo -e "${GREEN}✓ Final formatting applied${NC}"
fi
echo ""
echo -e "${GREEN}✓ All commits have been rebased and formatted${NC}"
echo ""
echo "To delete the backup:"
echo -e " ${BLUE}git branch -D $BACKUP_BRANCH${NC}"
else
echo ""
echo -e "${YELLOW}=== Rebase needs manual intervention ===${NC}"
echo ""
# Check for conflicts
CONFLICTED_FILES=$(git diff --name-only --diff-filter=U 2>/dev/null || true)
if [ -n "$CONFLICTED_FILES" ]; then
echo -e "${YELLOW}Files with conflicts:${NC}"
echo "$CONFLICTED_FILES" | while read -r file; do
echo " • $file"
done
echo ""
echo -e "${BLUE}Steps to resolve:${NC}"
echo "1. Fix merge conflicts in the files above"
echo "2. Run prettier on resolved files:"
echo -e " ${GREEN}npx prettier --write <file>${NC}"
echo "3. Stage the resolved files:"
echo -e " ${GREEN}git add <file>${NC}"
echo "4. Continue the rebase:"
echo -e " ${GREEN}git rebase --continue${NC}"
echo ""
echo "The prettier script will continue to run after each commit."
fi
echo ""
echo -e "${YELLOW}To abort and restore:${NC}"
echo " git rebase --abort"
echo " git checkout $BACKUP_BRANCH"
fi
# Clean up
rm -f "$PRETTIER_SCRIPT"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment