#!/bin/bash set -e # --- CONFIGURATION (Modify these for other projects/配置项) --- # 1. The Git URL of the official upstream repository (上游官方仓库地址) UPSTREAM_URL="https://github.com/TencentCloud/chat-uikit-flutter.git" # 2. List of local directories/files to PROTECT from upstream changes (space separated) # e.g. "images/ assets/custom_config.json" (需要保护的本地目录或文件,空格分隔) PROTECTED_PATHS="images/" # ------------------------------------------------------- # Colors for output GREEN='\033[0;32m' BLUE='\033[0;34m' RED='\033[0;31m' NC='\033[0m' # No Color echo -e "${BLUE}=== Starting Upstream Synchronization ===${NC}" # 1. Verify we are in the root of the repo for path in $PROTECTED_PATHS; do if [ ! -e "$path" ]; then echo -e "${RED}Warning: Protected path '$path' not found in current directory.${NC}" fi done # 2. Add upstream remote if not exists if ! git remote | grep -q "upstream"; then echo "Adding upstream remote..." git remote add upstream "$UPSTREAM_URL" fi # 2.1 Stash local changes to prevent data loss during branch switching echo -e "${BLUE}Stashing local changes...${NC}" STASH_NEEDED=false if ! git diff-index --quiet HEAD --; then git stash push -m "Stash before upstream sync" STASH_NEEDED=true fi # 3. Fetch upstream echo -e "${BLUE}Fetching latest upstream changes...${NC}" git fetch upstream # 4. Update upstream-main branch (The Reference Branch) echo -e "${BLUE}Updating upstream-main branch...${NC}" if git show-ref --verify --quiet refs/heads/upstream-main; then git checkout upstream-main git reset --hard upstream/main else git checkout -b upstream-main upstream/main fi # 5. Switch back to master echo -e "${BLUE}Switching to master...${NC}" git checkout master # 5.1 Save the current master commit BEFORE merge (Critical Fix) MASTER_BEFORE_MERGE=$(git rev-parse HEAD) # 6. Merge upstream-main into master echo -e "${BLUE}Merging upstream changes into master...${NC}" # We use --no-commit to allow us to check/restore images before finalizing if git merge --no-commit upstream-main; then echo "Merge prepared successfully." else echo -e "${RED}Merge conflict detected.${NC}" echo "Attempting to auto-resolve protected paths conflicts by keeping OURS..." # If conflict is in protected paths, we force checkout master's version (before merge) for path in $PROTECTED_PATHS; do git checkout "$MASTER_BEFORE_MERGE" -- "$path" || true done echo "Note: Manual resolution may still be required for non-protected files." fi # 7. FORCE RESTORE PROTECTED PATHS (The Core Protection) # Regardless of merge status, we ensure protected folders are exactly what we had before echo -e "${BLUE}Ensuring protected paths are preserved...${NC}" for path in $PROTECTED_PATHS; do git checkout "$MASTER_BEFORE_MERGE" -- "$path" done # 8. Check for conflicts if git ls-files -u | grep -q .; then echo -e "${RED}!!! CONFLICTS REMAINING !!!${NC}" echo "Please resolve conflicts manually (e.g. in lib/...), then commit." echo "Note: Your protected paths ($PROTECTED_PATHS) have already been restored." exit 1 else echo -e "${GREEN}No conflicts or conflicts resolved.${NC}" # If we are in a merge state (MERGE_HEAD exists), commit it if [ -f .git/MERGE_HEAD ]; then git commit -m "chore: sync with upstream $(date +%Y-%m-%d) (preserve local customizations)" echo -e "${GREEN}Merge committed successfully!${NC}" else echo "Nothing to commit (already up to date)." fi fi echo -e "${GREEN}=== Synchronization Complete ===${NC}" if [ "$STASH_NEEDED" = true ]; then echo -e "${BLUE}Restoring stashed changes...${NC}" if git stash pop; then echo -e "${GREEN}Local changes restored successfully.${NC}" else echo -e "${RED}Conflict detected while restoring stashed changes. Please resolve manually.${NC}" fi fi