113 lines
3.6 KiB
Bash
Executable File
113 lines
3.6 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m' # No Color
|
|
|
|
failed_repos=()
|
|
failed_msgs=()
|
|
success_repos=()
|
|
|
|
gitdirs=$(find . -type d -name ".git")
|
|
|
|
for gitdir in $gitdirs; do
|
|
repo=$(dirname "$gitdir")
|
|
cd "$repo" || continue
|
|
echo -e "${CYAN}📁 Processing: $repo${NC}"
|
|
repo_failed=0
|
|
msg=""
|
|
|
|
# Stash uncommitted changes if any
|
|
uncommitted=$(git status --porcelain | wc -l | tr -d ' ')
|
|
stashed=0
|
|
if [ "$uncommitted" -gt 0 ]; then
|
|
echo -e " ${YELLOW}Stashing $uncommitted uncommitted change(s)...${NC}"
|
|
if git stash push -u -m "Auto-stash before rebase and push by script"; then
|
|
stashed=1
|
|
else
|
|
echo -e " ${RED}Failed to stash changes! Skipping repo.${NC}"
|
|
repo_failed=1
|
|
msg="Failed to stash changes."
|
|
fi
|
|
fi
|
|
|
|
if [ "$repo_failed" -eq 0 ]; then
|
|
# Fetch and rebase
|
|
git remote update > /dev/null 2>&1
|
|
if git rev-parse --abbrev-ref --symbolic-full-name @{u} > /dev/null 2>&1; then
|
|
echo -e " ${YELLOW}Rebasing onto upstream...${NC}"
|
|
if ! git rebase @{u}; then
|
|
echo -e " ${RED}Rebase failed! Attempting to abort and restore stash.${NC}"
|
|
git rebase --abort
|
|
repo_failed=1
|
|
msg="Rebase failed."
|
|
fi
|
|
else
|
|
echo -e " ${RED}No upstream branch set. Skipping rebase and push.${NC}"
|
|
repo_failed=1
|
|
msg="No upstream branch set."
|
|
fi
|
|
fi
|
|
|
|
if [ "$repo_failed" -eq 0 ]; then
|
|
# Push local-only commits if any
|
|
ahead=$(git rev-list --count @{u}..HEAD 2>/dev/null)
|
|
if [ "$ahead" -gt 0 ]; then
|
|
echo -e " ${YELLOW}Pushing $ahead local commit(s) to remote...${NC}"
|
|
if ! git push; then
|
|
echo -e " ${RED}Push failed!${NC}"
|
|
repo_failed=1
|
|
msg="Push failed."
|
|
fi
|
|
else
|
|
echo -e " ${GREEN}No local-only commits to push.${NC}"
|
|
fi
|
|
fi
|
|
|
|
# Restore stashed changes if any
|
|
if [ "$stashed" -eq 1 ]; then
|
|
echo -e " ${YELLOW}Restoring stashed changes...${NC}"
|
|
if ! git stash pop; then
|
|
echo -e " ${RED}Stash pop failed! You may need to resolve conflicts manually.${NC}"
|
|
repo_failed=1
|
|
msg="Stash pop failed."
|
|
fi
|
|
fi
|
|
|
|
# Final check
|
|
ahead_final=0
|
|
if git rev-parse --abbrev-ref --symbolic-full-name @{u} > /dev/null 2>&1; then
|
|
ahead_final=$(git rev-list --count @{u}..HEAD 2>/dev/null)
|
|
fi
|
|
if [ "$repo_failed" -eq 0 ] && [ "$ahead_final" -eq 0 ]; then
|
|
echo -e " ${GREEN}✅ Repo is up to date with remote. No local-only commits.${NC}"
|
|
success_repos+=("$repo")
|
|
else
|
|
if [ "$repo_failed" -eq 0 ]; then
|
|
msg="Still $ahead_final local-only commit(s) after push!"
|
|
fi
|
|
echo -e " ${RED}❌ $msg${NC}"
|
|
failed_repos+=("$repo")
|
|
failed_msgs+=("$msg")
|
|
fi
|
|
|
|
echo -e "${CYAN}──────────────────────────────────────────────${NC}"
|
|
cd - > /dev/null || exit
|
|
done
|
|
|
|
# Summary
|
|
printf "\n${CYAN}===== SUMMARY =====${NC}\n"
|
|
if [ ${#success_repos[@]} -gt 0 ]; then
|
|
echo -e "${GREEN}Repos successfully rebased and pushed:${NC}"
|
|
for repo in "${success_repos[@]}"; do
|
|
echo -e " $repo"
|
|
done
|
|
fi
|
|
if [ ${#failed_repos[@]} -gt 0 ]; then
|
|
echo -e "\n${RED}Repos with issues:${NC}"
|
|
for i in "${!failed_repos[@]}"; do
|
|
echo -e " ${failed_repos[$i]}: ${failed_msgs[$i]}"
|
|
done
|
|
fi |