Managing multiple feature branches in a Laravel project can be tedious—especially when you need to rebase them all onto master before a release. Instead of manually running the same Git commands for each branch, automate it with a shell script.
The Manual Process
# For each branch, manually run:
git checkout master
git checkout origin/feature/user-dashboard
git rebase master
git push origin HEAD:feature/user-dashboard --force
git checkout master
git checkout origin/feature/api-endpoints
git rebase master
git push origin HEAD:feature/api-endpoints --force
# ...repeat for every branch
This is error-prone and wastes time. You might forget a branch, push to the wrong remote, or leave the repository in a bad state if you hit conflicts.
The Automated Approach
Create a rebase-branches.sh script that handles the entire workflow with proper error handling:
#!/bin/bash
# rebase-branches.sh
set -e
# Parse arguments
TARGET_BRANCH="master"
while [[ $# -gt 0 ]]; do
case $1 in
-t|--target)
TARGET_BRANCH="$2"
shift 2
;;
*)
BRANCHES+=("$1")
shift
;;
esac
done
# Validate repository
REMOTE_URL=$(git remote get-url origin 2>/dev/null || echo "")
if [[ "$REMOTE_URL" != "[email protected]:yourcompany/yourapp.git" ]]; then
echo "Error: Must run from correct repository"
exit 1
fi
echo "Fetching from origin..."
git fetch origin
SKIPPED=()
SUCCESSFUL=()
for branch in "${BRANCHES[@]}"; do
echo "Processing: $branch"
# Checkout target branch
if ! git checkout "$TARGET_BRANCH" 2>/dev/null; then
SKIPPED+=("$branch (checkout failed)")
continue
fi
# Checkout feature branch from origin
if ! git checkout "origin/$branch" 2>/dev/null; then
SKIPPED+=("$branch (branch not found)")
continue
fi
# Attempt rebase
if git rebase "$TARGET_BRANCH" 2>/dev/null; then
# Force push if successful
if git push origin "HEAD:$branch" --force 2>/dev/null; then
SUCCESSFUL+=("$branch")
else
SKIPPED+=("$branch (push failed)")
git rebase --abort 2>/dev/null || true
fi
else
# Abort on conflicts
git rebase --abort 2>/dev/null || true
SKIPPED+=("$branch (conflicts)")
fi
done
# Return to target branch
git checkout "$TARGET_BRANCH" 2>/dev/null || true
# Report results
echo "Successfully rebased: ${#SUCCESSFUL[@]}"
for branch in "${SUCCESSFUL[@]}"; do
echo " ✓ $branch"
done
if [ ${#SKIPPED[@]} -gt 0 ]; then
echo "Skipped (conflicts/errors): ${#SKIPPED[@]}"
for branch in "${SKIPPED[@]}"; do
echo " ✗ $branch"
done
fi
Usage
# Make it executable
chmod +x rebase-branches.sh
# Rebase onto master (default)
./rebase-branches.sh feature/user-dashboard feature/api-endpoints feature/admin-tools
# Rebase onto a different branch
./rebase-branches.sh -t develop feature/user-dashboard feature/api-endpoints
What It Does
- Validates repository: Prevents accidentally running it in the wrong project
- Fetches from origin: Ensures you’re working with latest remote changes
- Handles conflicts gracefully: Aborts rebase and continues to next branch instead of leaving you in a broken state
- Reports results: Shows you exactly which branches succeeded and which had issues
- Returns to safe state: Always checks out the target branch when done
Why This Matters
Automating repetitive Git workflows saves time and reduces errors. This script is idempotent—if something fails, it cleans up and moves on without leaving your repository in a broken state. Perfect for teams managing multiple long-running feature branches that need frequent rebasing onto master or develop.
The script pattern can be adapted for other batch Git operations: merging multiple branches, deleting stale branches, or updating multiple repositories at once.
Leave a Reply